Cette question n'est pas subjective. Un verbe très spécifique est utilisé dans le livre référencé, et j'aimerais comprendre quelle est l'implication de cette formulation, car j'ai bien peur de mal comprendre quelque chose.
De Learn You a Haskell , le paragraphe suivant est le troisième et dernier contenant "nous supposons *
".
data Barry t k p = Barry { yabba :: p, dabba :: t k }
Et maintenant, nous voulons en faire une instance de
Functor
.Functor
veut des types de genre* -> *
maisBarry
ne semble pas avoir ce genre. Quel est le genre deBarry
? Eh bien, nous voyons qu'il faut trois paramètres de type, donc ça va êtresomething -> something -> something -> *
. Il est sûr de dire quep
c'est un type concret et a donc une sorte de*
. Cark
, nous supposons*
et donc par extension,t
a une sorte de* -> *
. Maintenant, remplaçons simplement ces types par lessomething
s que nous avons utilisés comme espaces réservés et nous voyons qu'il a une sorte de(* -> *) -> * -> * -> *
.
Pourquoi supposons-nous quelque chose? En lisant «nous supposons X (c'est-à-dire que nous supposons que X est vrai)», il est naturel pour moi de penser que nous devrions également considérer le cas où X est faux. Dans le cas spécifique de l'exemple, ne pourrait-il pas t
être de nature (* -> *) -> *
et k
de nature (* -> *)
? Si tel était le cas, quoi qu'il en soit t
et en k
réalité, ce t k
serait toujours un type concret, non?
Je vois que toute la ligne de raisonnement est ensuite vérifiée par rapport au compilateur, mais je ne pense pas que le compilateur suppose . Si c'est le cas, j'aimerais savoir quoi, si ce n'est pas le cas, je crains de manquer le sens du paragraphe.
k :: L
pour tout typeL
, aussi longtemps quet :: L -> *
. Un compilateur ici doit cependant en choisir un spécifiqueL
, ou recourir à une polykind. Une polykind serait l'option la plus générale, mais ici GHC choisitL = *
(Haskell de base n'a pas de polykinds, ils doivent être activés en tant qu'extension). Puisqu'il choisit quelque chose qui est plutôt arbitraire, LYAH utilise le mot "assumer" (AFAICT).Réponses:
En fait, le compilateur suppose! Mais vous pouvez lui demander de ne pas le faire avec l'extension PolyKinds. Vous pouvez en lire plus en détail ici . Avec cette extension activée, le genre de
Barry
seraforall k. (k -> *) -> k -> * -> *
.la source
Bon point. L'auteur fait une supposition inutile. Peut-être juste pour le rendre plus facile à comprendre dans son chapitre Type Foo, mais des gens comme vous peuvent à juste titre remettre cela en question.
Les deux
t
,k
etp
sont des variables de type. Comme nous le voyons,yabba :: p
il peut vivre seul, c'est donc comme une fonction constante, comme s'il s'agissait d'une valeur au lieu d'un type, sa signature de type diraitInt
ouChar
, peu importe ... vous l'appelez. Mais comme c'est un type, c'est sa signature aimable*
.Cependant,
t
type ici prend une variable de typek
pour construire un type (dabba :: t k
)donc nous sommes sûrs que (aucune supposition ici).t
n'a une sorte de signature comme* -> *
etk
a*
Une fois que nous savons cela ... la
Barry t k p
sorte de signature du type est(* -> *) -> * -> * -> *
ce qui signifie qu'il faut det
temps enk
tempsp
et nous donner leBarry
type.Modifier Assurez-vous de lire le commentaire de @ luqui ci-dessous.
la source
k
n'est pas contraint d'être*
comme vous le prétendez tout en déduisantt
. Nous aurions puk :: * -> *
ett :: (* -> *) -> *
, par exemple. Ajoutez un champdoo :: k Int
à l'enregistrement et il passera sans problème.