Como é que Haskell sabe qual instância typeclass você quer dizer?
-
03-07-2019 - |
Pergunta
Esta questão surgiu durante a leitura do novo capítulo na excelente Saiba Você é uma Haskell sobre functors aplicativas.
O typeclass Applicative tem, como parte da definição para a instância Talvez:
pure = Just
Se eu ir para GHCi e importar Control.Applicative, e fazer:
pure (3+)
Eu não entendo Apenas qualquer coisa (faz sentido). Mas se eu usá-lo em parte da expressão:
pure (3+) <*> Just 4
Eu recebo apenas 7. Eu acho que também não é surpreendente, mas eu estou faltando alguma coisa integrante sobre como typeclasses trabalho, eu acho, que não há ambigüidade com a chamada para pure
aqui.
Se a minha confusão faz sentido, alguém pode explicar o que está acontecendo em detalhes?
Solução
É apenas inferência de tipos. O operador (<*>)
requer que ambos os argumentos para usar a mesma instância Applicative
. O lado direito é uma Maybe
, de modo que o lado esquerdo tem que ser um Maybe
também. Então é assim que descobre qual instância é usado aqui. Você pode olhar para o tipo de qualquer expressão no interpretador por :t expression
digitação, e talvez se você acabou de passar por cada sub-expressão e olhar para o tipo que foi inferida, você vai obter uma melhor imagem do que está acontecendo.
Outras dicas
Vale a pena olhar para o tipo dos infere do compilador para pure (3+)
:
Prelude Control.Applicative> :t pure (3+)
pure (3+) :: (Num a, Applicative f) => f (a -> a)
O tipo de este termo está sobrecarregado, ea decisão sobre a classe numérica ea classe aplicativo é adiada para mais tarde. Mas você pode forçar um tipo particular com uma anotação, por exemplo:
*Showfun Control.Applicative> pure (3+) :: Maybe (Double -> Double)
Just <function>
(Isso funciona porque Showfun
tem uma declaração exemplo que imprime um valor de função como <function>
.)
É apenas uma questão de quando o compilador tem acumulado informações suficientes para tomar uma decisão.
Para expandir um pouco sobre a resposta de newacct, se não houver informação suficiente para inferir o tipo real, o compilador pode (em alguns casos) tentar selecionar um tipo padrão, limitado àqueles que satisfaça as restrições de tipo em questão . Neste caso, o tipo inferido é IO (n -> n) para alguns difícil de determinar instância Num => n. GHCi seguida, avalia-lo e joga fora o valor de retorno, sem nenhum efeito visível.
Aqui está um interessante sobre a inferência de tipos . Não Haskell específico, mas muitas boas ligações e coisas para ler sobre a inferência de tipos em linguagens funcionais.