Outil ou méthode de résolution des paramètres de type générique Haskell [dupliquer]
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 id
et traverse
ensemble 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 ( id
et 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
, t
sont mis en correspondance à des types de béton.
Je veux attraper et montrer ce mappage automatiquement.
Réponses
Je pense f
et t
sont 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 id
n'est pas la composition, il est l' application de la fonction, vous passez id
comme un argument de à traverse
. this . that
est une composition de fonction entre this
et that
, au sens mathématique du terme, où vous créez une fonction qui donne son (premier) argument en entrée that
et 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 ord
est [Char] -> [Int]
, comme vous pouvez le vérifier vous-même en écrivant :t map ord
sur 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 id
s'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 b
qui traverse
attend, 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
.