Outil ou méthode de résolution des paramètres de type générique Haskell [dupliquer]

Dec 12 2020

Regardons les types de ces fonctions par exemple:

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

:t id
id :: a -> a

Ils ont aucun type de béton, mais ont des paramètres de type générique : a, f, b, t(corrigez - moi s'ils ont appelé pas les paramètres de type générique svp)

Si je combine idet traverseensemble de cette manière,

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

Haskell peut maintenant lier certains types de béton pour les variables de type a, f, b, t.

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

Ci-dessous, j'infère les types et les mappages aux paramètres à la main, y a-t-il un moyen ou un outil dans Haskell pour le faire automatiquement, de sorte qu'il prenne certaines parties composées ( idet traverse) dans un exemple, extrait leurs signatures de type en général, et en sortie produit une correspondance entre les noms de paramètres de type générique et les types inférés concrets?

Voir aussi le premier exemple ici: https://wiki.haskell.org/Type_inferencepour l'expression " map ord" sur la façon dont Haskell trouve les liaisons de types réels aux noms.

Donc , quand on regarde séparément les fonctions que nous avons seulement des noms a, f, b, t. Mais nous combinons les fonctions et de fournir des informations supplémentaires comme [Just 1, Just 2, Nothing], et les noms a, f, b, tsont mis en correspondance à des types de béton.

Je veux attraper et montrer ce mappage automatiquement.

Réponses

Enlico Dec 12 2020 at 00:55

Je pense fet tsont plus génériques constructeur de type paramètres , car ils agissent sur un type pour vous donner un type (ils genre est * -> *, où des *moyens « un type de béton »).

traverse idn'est pas la composition, il est l' application de la fonction, vous passez idcomme un argument de à traverse. this . thatest une composition de fonction entre thiset that, au sens mathématique du terme, où vous créez une fonction qui donne son (premier) argument en entrée thatet alimente le résultat de cette application this.

Vous vous référez à l'exemple de cette page, où étant donné ce

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

le compilateur est capable de déduire que le type de map ordest [Char] -> [Int], comme vous pouvez le vérifier vous-même en écrivant :t map ordsur la ligne de commande.

Si vous attendez une sortie similaire avec des types concérés lorsque vous tapez :t traverse id, vous ne l'obtiendrez pas, pour la simple raison qu'il traverse ids'agit toujours d'une fonction polymorphe, à la fois dans ses arguments de type concret et dans ses arguments de constructeur de type.

Juste pour donner un exemple légèrement différent, si vous tapez :t traverse (:[]), where (:[])has type a -> [a], qui est un cas particulier de celui (Applicative f) => a -> f bqui traverseattend, vous obtenez cette sortie,

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

qui, par rapport à :t traverse,

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

vous indique que traverse, dans traverse (:[]), a été "instancié" avec f === []et a === b.