Ferramenta ou método de resolução de parâmetros de tipo genérico Haskell [duplicado]

Dec 12 2020

Vejamos os tipos dessas funções, por exemplo:

:t traverse
traverse
  :: (Applicative f, Traversable t) => (a -> f b) -> t a -> f (t b)

:t id
id :: a -> a

Eles não têm tipos de concreto, mas têm parâmetros de tipo genérico : a, f, b, t(me corrija se chamavam não parâmetros de tipo genérico , por favor)

Se eu combinar ide traversejuntar desta forma,

:t traverse id [Just 1, Just 2, Nothing] 
traverse id [Just 1, Just 2, Nothing] :: Num b => Maybe [b]

Haskell podem agora ligar-se alguns tipos de concreto para as variáveis tipo a, f, b, t.

t = []
a = Maybe bb
f = Maybe
b = Num bb => bb

Abaixo eu deduzo os tipos e mapeamentos para parâmetros manualmente, há alguma maneira ou ferramenta em Haskell para fazer isso automaticamente, de modo que pegue algumas partes compostas ( ide traverse) em um exemplo, extraia suas assinaturas de tipo em geral e na saída produz um mapeamento de nomes de parâmetros de tipo genérico para tipos inferidos concretos?

Veja também o primeiro exemplo aqui: https://wiki.haskell.org/Type_inferencepara a expressão " map ord" em como Haskell encontra ligações de tipos reais para nomes.

Assim, quando olhamos para funções separadamente só temos nomes a, f, b, t. Mas, então, combinar as funções e fornecer algumas informações extra como [Just 1, Just 2, Nothing], e os nomes a, f, b, tsão mapeados para tipos de concreto.

Quero capturar e mostrar esse mapeamento automaticamente.

Respostas

Enlico Dec 12 2020 at 00:55

Eu penso fe tsão mais genéricas tipo construtor parâmetros , como eles agem em um tipo para lhe dar um tipo (que tipo é * -> *, em que *os meios "um tipo concreto").

traverse idNão é a composição, é a aplicação de função, como você está passando idcomo um argumento para traverse. this . thaté a composição da função entre thise that, no sentido matemático, onde você cria uma função que fornece seu (primeiro) argumento como uma entrada para thate alimenta o resultado desta aplicação para this.

Você se refere ao exemplo nesta página, onde dado este

map :: (a -> b) -> [a] -> [b]
Char.ord :: (Char -> Int)

o compilador é capaz de deduzir que o tipo de map ordé [Char] -> [Int], como você mesmo pode verificar escrevendo :t map ordna linha de comando.

Se você espera uma saída semelhante com tipos conceretos ao digitar :t traverse id, não a obterá, pelo simples motivo de que traverse idainda é uma função polimórfica, tanto em seus argumentos de tipo concreto quanto em argumentos de construtor de tipo.

Apenas para dar um exemplo um pouco diferente, se você digitar :t traverse (:[]), onde (:[])tem tipo a -> [a], que é um caso particular do (Applicative f) => a -> f bque traverseespera, você obterá esta saída,

traverse (:[]) :: Traversable t => t b -> [t b]

que, comparado com :t traverse,

traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)

informa que traverse, em traverse (:[]), foi "instanciado" com f === []e a === b.