Pergunta

Desculpas antecipadamente se essa pergunta for um pouco vaga. É o resultado de alguns fins de semana sonham no fim de semana.

Com o maravilhoso sistema do tipo Haskell, é deliciosamente agradável expressar a estrutura matemática (especialmente algébrica) como tipo de tipo de tipo. Quero dizer, apenas dê uma olhada Promoção numérica! Mas aproveitar uma estrutura de tipo tão maravilhosa na prática sempre me pareceu difícil.

Você tem uma maneira agradável e de sistema de expressar isso v1 e v2 são elementos de um espaço vetorial V e essa w é um elemento de um espaço vetorial W. O sistema de tipo permite escrever um programa adicionando v1 e v2, mas não v1 e w. Excelente! Mas, na prática, você pode querer brincar com potencialmente centenas de espaços vetoriais, e você certamente não quer criar tipos V1, V2, ..., V100 e os declare instâncias do espaço vetorial TypeClass! Ou talvez você leia alguns dados do mundo real, resultando em símbolos a, b e c - Você pode expressar que o espaço vetorial livre sobre esses símbolos é realmente um espaço vetorial!

Então você está preso, certo? Para fazer muitas das coisas que você gostaria de fazer com os espaços vetoriais em uma configuração de computação científica, você precisa desistir do seu sistema de tipo datatrimonados renunciando a um tipo de tipo de espaço vetorial e com funções faz verificações de compatibilidade em tempo de execução. Você deve ter que? Não deveria ser possível usar o fato de que Haskell é puramente funcional para escrever um programa que gera todos os tipos de que você precisa e os insere no programa real? Essa técnica existe? Por todos os meios, aponte se estou simplesmente negligenciando algo básico aqui (provavelmente sou) :-)

Editar: Agora eu descobri FUNDEPS. Vou ter que pensar um pouco sobre como eles se relacionam com minha pergunta (comentários esclarecedores com relação a isso são apreciados).

Foi útil?

Solução

Modelo Haskell permite isso. o Página da wiki tem alguns links úteis; particularmente Bulat's tutoriais.

A sintaxe da declaração de nível superior é a que você deseja. Digitando:

mkFoo = [d| data Foo = Foo Int |]

Você gera um modelo Haskell Splice (como uma função de tempo de compilação) que criará uma declaração para data Foo = Foo Int apenas inserindo a linha $(mkFoo).

Embora esse pequeno exemplo não seja muito útil, você pode fornecer um argumento ao MKFOO para controlar quantas declarações diferentes você deseja. Agora a $(mkFoo 100) produzirá 100 novas declarações de dados para você. Você também pode usar o TH para gerar instâncias de classe de tipo. Meu Tupla adaptativa O pacote é um projeto muito pequeno que usa o modelo Haskell para fazer algo semelhante.

Uma abordagem alternativa seria usar Derivar, que derivará automaticamente instâncias de classe de tipo. Isso pode ser mais simples se você precisar apenas das instâncias.

Outras dicas

Também existem algumas técnicas simples de programação em nível de tipo em Haskell. Um exemplo canônico a seguir:

-- A family of types for the natural numbers
data Zero
data Succ n

-- A family of vectors parameterized over the naturals (using GADTs extension)
data Vector :: * -> * -> * where
    -- empty is a vector with length zero
    Empty :: Vector Zero a
    -- given a vector of length n and an a, produce a vector of length n+1
    Cons  :: a -> Vector n a -> Vector (Succ n) a

-- A type-level adder for natural numbers (using TypeFamilies extension)
type family Plus n m :: *
type instance Plus Zero n = n
type instance Plus (Succ m) n = Succ (Plus m n)

-- Typesafe concatenation of vectors:
concatV :: Vector n a -> Vector m a -> Vector (Plus n m) a
concatV Empty ys = ys
concatV (Cons x xs) ys = Cons x (concatV xs ys)

Reserve um momento para aceitar isso. Acho que é bastante mágico que funcione.

No entanto, a programação em nível de tipo em Haskell está no valor da revista de recursos-apenas o suficiente para chamar a atenção para o quanto você não pode fazer. Idiomas dependentes como AGDA, Coq, e Epigrama Leve esse estilo ao seu limite e potência total.

O modelo Haskell é muito mais parecido com o estilo usual de geração de código Lisp-Macro. Você escreve algum código para escrever algum código e diz "OK, insira esse código gerado aqui". Ao contrário da técnica acima, você pode escrever qualquer código especificado de forma computável dessa maneira, mas não obtém o tipo de digitação geral como é visto em concatV acima de.

Então você tem algumas opções para fazer o que quiser. Eu acho que a metaprogramação é um espaço realmente interessante e, de certa forma, ainda é muito jovem. Divirta -se explorando. :-)

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