Qual é a suposição feita em “Learn You a Haskell” ao deduzir o tipo?

18

Esta questão não é subjetiva. Um verbo muito específico é usado no livro referenciado, e eu gostaria de entender qual é a implicação dessa frase, porque temo estar entendendo mal alguma coisa.

De Learn You a Haskell , o parágrafo a seguir é o terceiro e o último que contém "assumimos *".

data Barry t k p = Barry { yabba :: p, dabba :: t k }  

E agora queremos fazer disso uma instância do Functor. Functorquer tipos do tipo, * -> *mas Barrynão parece ter esse tipo. Qual é o tipo de Barry? Bem, vemos que são necessários três parâmetros de tipo, então será something -> something -> something -> *. É seguro dizer que pé um tipo concreto e, portanto, tem um tipo de *. Pois k, assumimos *e, por extensão, ttem uma espécie de* -> * . Agora, vamos substituir esses tipos pelos somethings que usamos como espaços reservados e vemos que tem um tipo de (* -> *) -> * -> * -> *.

Por que estamos assumindo alguma coisa? Ao ler "assumimos X (ou seja, assumimos que X é verdadeiro)", é natural para mim pensar que também devemos considerar o caso de que X é falso. No caso específico do exemplo, não poderia tser do tipo (* -> *) -> *e kdo tipo (* -> *)? Se fosse esse o caso, qualquer que fosse te krealmente fosse, t kainda seria um tipo concreto, não?

Vejo que toda a linha de raciocínio é então verificada no compilador, mas não acho que o compilador assuma . Se isso acontecer, gostaria de saber o que, se não acontecer, novamente. Receio estar perdendo o significado do parágrafo.

Enrico Maria De Angelis
fonte
4
Você está certo. De fato, podemos ter k :: Lpara qualquer tipo L, desde que t :: L -> *. Um compilador aqui deve, no entanto, escolher alguns específicos Lou recorrer a uma polignidade. Uma poli-classe seria a opção mais geral, mas aqui o GHC escolhe L = *(Haskell básico não tem poli-classes, elas precisam ser ativadas como uma extensão). Como escolhe algo arbitrário, a LYAH usa a palavra "assumir" (AFAICT).
chi
11
Ok, talvez o compilador assuma que teria me intrigado pelo menos menos do que imaginamos , ou nem um pouco.
Enrico Maria De Angelis

Respostas:

19

De fato, o compilador assume! Mas você pode pedir que não o faça com a extensão PolyKinds. Você pode ler sobre isso com mais detalhes aqui . Com essa extensão ativada, o tipo de Barryserá forall k. (k -> *) -> k -> * -> *.

Daniel Wagner
fonte
-1

Bom ponto. O autor faz uma suposição desnecessária. Talvez apenas para facilitar a compreensão em seu capítulo Type Foo, mas pessoas como você podem legitimamente questionar isso.

Ambos t, ke psão variáveis de tipo. Como podemos ver, yabba :: pele pode viver sozinho, então é como uma função constante, como se fosse um valor em vez de um tipo, sua assinatura de tipo diria Intou Char, seja o que for ... o nome dele. Mas como é um tipo, é uma assinatura gentil *.

No entanto, ttype aqui utiliza uma variável de tipo kpara construir um type ( dabba :: t k), portanto, temos certeza de que (sem suposição aqui) tpossui uma assinatura de tipo como * -> *e kpossui* .

Uma vez que sabemos que isso ... o tipo Barry t k pde assinatura tipo é (* -> *) -> * -> * -> *o que significa que é preciso t, em seguida, ke, em seguida, pe dar-nos Barryescrever.

Editar Certifique-se de ler o comentário de @ luqui abaixo.

Redu
fonte
7
knão é restrito a ser *como você afirma que é ao deduzir t. Poderíamos ter k :: * -> *e t :: (* -> *) -> *, por exemplo. Adicione um campo doo :: k Intao registro e ele passará sem problemas.
luqui 8/12/19
@luqui .. Sim, você está certo ... Não vou excluir esta resposta, já que seu comentário realmente vale a pena.
Redu