Pergunta

Pode ML ficheiro ser expressa de maneira prática com .NET interfaces e os genéricos?Há uma avançada ML functor usar o exemplo que desafia a tais codificações?

Respostas resumo:

No caso geral, a resposta é NÃO.ML módulos fornecem funcionalidades (tais como especificação de compartilhamento por meio de assinaturas [1]) que não diretamente mapa .NET conceitos.

No entanto, para determinados casos de uso o ML expressões idiomáticas podem ser traduzidas.Esses casos incluem não apenas o básico Set functor [2], mas também a functorial codificação de mônadas [3] e ainda mais avançada usa de som, tais como, finalmente, tagless intérpretes [4, 5].

Prática codificações exigir compromissos, tais como semi-seguro downcasts.Sua milhagem vai desconfiar.

Blogs e de código:

  1. blog.matthewdoig.com
  2. higherlogics.blogspot.com
  3. mônada functor F#
Foi útil?

Solução

Um dos principais recursos dos módulos ML está compartilhando especificações. Não há nenhum mecanismo no .NET que seria capaz de imitá-los -. A maquinaria necessária é muito diferente

Você pode tentar fazê-lo girando os tipos compartilhados em parâmetros, mas isso não pode fielmente emular a capacidade de definir uma assinatura, e depois aplicar compartilhando a ele, talvez de várias maneiras diferentes.

Na minha opinião, .NET se beneficiaria de algo que tinha este tipo de máquinas - seria então aproximar-se verdadeiramente apoiar a diversidade de línguas modernas. Esperemos incluindo avanços mais recentes em sistemas de módulos como aqueles em MixML, que na minha opinião é o futuro dos sistemas de módulos. http://www.mpi-sws.org/~rossberg/mixml/

Outras dicas

HigherLogics é o meu blog, e eu passei muito tempo a investigar esta questão.A limitação é, de fato, abstração sobre o tipo de construtores, também conhecido como "genéricos sobre genéricos".Parece que o melhor que você pode fazer para imitar ML e módulos de ficheiro requer pelo menos um (semi-safe) cast.

Basicamente, ele vem para baixo para definir um tipo abstrato, e uma interface que corresponde ao módulo de assinatura que opera sobre que tipo.O resumo tipo e a interface compartilhar um parâmetro de tipo B, o que chamo de uma "marca";a marca é, geralmente, apenas o subtipo que implementa o módulo de interface.A marca garante que o tipo de passado é adequada subtipo esperado pelo módulo.

// signature
abstract class Exp<T, B> where B : ISymantics<B> { }
interface ISymantics<B> where B : ISymantics<B>
{
  Exp<int, B> Int(int i);
  Exp<int, B> Add(Exp<int, B> left, Exp<int, B> right);
}
// implementation
sealed class InterpreterExp<T> : Exp<T, Interpreter>
{
  internal T value;
}
sealed class Interpreter : ISymantics<Interpreter>
{
  Exp<int, Interpreter> Int(int i) { return new InterpreterExp<int> { value = i }; }
  Exp<int, Interpreter> Add(Exp<int, Interpreter> left, Exp<int, Interpreter> right)
  {
    var l = left as InterpreterExp<int>; //semi-safe cast
    var r = right as InterpreterExp<int>;//semi-safe cast
    return new InterpreterExp<int> { value = l.value + r.value; }; }
  }
}

Como você pode ver, o elenco é composto principalmente de segurança, uma vez que o tipo de sistema garante a marca do tipo de expressão coincide com a marca do intérprete.A única forma de parafuso isso, é se o cliente cria a sua própria Exp de classe e especifica o Intérprete da marca.Existe um seguro de codificação que evita esse problema também, mas é muito pesado para um processo de programação.

Mais tarde eu usado esta codificação e traduzido exemplos a partir de um dos Oleg papéis escritos em MetaOCaml, para usar o C# e Linq.O intérprete pode, de forma transparente, a execução de programas escritos usando este incorporado linguagem do lado do servidor em ASP.NET ou client-side, como JavaScript.

Esta abstração sobre intérpretes é um recurso de Oleg final tagless de codificação.Links para o seu papel e são fornecidos em um post no blog.

Interfaces são de primeira classe .LÍQUIDO, e, uma vez que usar interfaces para codificar módulo de assinaturas, módulos e módulo de assinaturas também são de primeira classe neste codificação.Assim, o ficheiro basta usar a interface diretamente no lugar do módulo de assinaturas, ou seja,.eles iriam aceitar uma instância de ISymantics<B> e delegar as chamadas para ele.

Eu não sei functors ML bem o suficiente para realmente responder a sua pergunta. Mas vou dizer o fator limitante da Net eu sempre encontrar com monádico programação é a incapacidade de mais abstrato 'M' no sentido de "forall M. alguma expressão tipo com M < T> "(por exemplo, onde M é um construtor de tipo (tipo que leva um ou argumentos mais genéricos)). Então, se isso é algo que às vezes precisam / uso com functors, então me sinto muito confiante de que não há nenhuma boa maneira de expressá-lo na Net.

Eu já postou uma descrição detalhada da minha tradução de módulos mL, assinaturas e functors a um C # codificação equivalente. Espero que alguém acha útil.

O comentário de Brian no local. Aqui está o código OCaml que usa functors para dar uma implementação (estrita) de Haskell sequence :: (Monad m) => [m a] -> m [a] parametrizados sobre a Mônada em questão:

module type Monad = 
sig
  type 'a t (*'*)
  val map : ('a -> 'b) -> ('a t -> 'b t)
  val return : 'a -> 'a t
  val bind : 'a t -> ('a -> 'b t) -> 'b t
end

module type MonadUtils =
sig
  type 'a t (*'*)
  val sequence : ('a t) list -> ('a list) t
end

module MakeMonad (M : Monad) : MonadUtils =
struct
  type 'a t = 'a M.t
  let rec sequence = function
    | [] -> 
        M.return []
    | x :: xs ->
        let f x = 
          M.map (fun xs -> x :: xs) (sequence xs)
        in 
          M.bind x f
end

Isso parece difícil de expressar em .NET.

Atualizar :

Usando uma técnica por naasking eu era capaz de codificar a função sequence reutilizável em F # em uma maneira de tipo seguro na sua maioria (usos operações de downcast).

http://gist.github.com/192353

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top