Haskell - Utiliser Just or no Just fait la différence, mais je ne sais pas pourquoi

StackOverflow https://stackoverflow.com/questions/3261844

  •  16-09-2020
  •  | 
  •  

Question

J'ai trouvé un tel code dans le livre "Real World Haskell", p68

data Tree a = Node a (Tree a) (Tree a)
            | Empty
              deriving (Show)

nodeAreSame (Node a _ _) (Node b _ _)
            | a == b = Just a
nodeAreSame _ _ = Nothing

Ma question est:Quel travail a fait le Just le constructeur de données fait-il ?Lorsque je le supprimerai, j'obtiendrai un message d'erreur tel que

(in ghci)
......
<Main *> nodeAreSame (Node 3 Empty Empty) (Node 3 Empty Empty))  

<interactive>:1:16:  
    No instance for (Num (Maybe a))
......

Mais quand j'essaie de comparer la différence de type entre les versions "Just" et "No Just":

nodeAreSameJust   :: (Eq t) => Tree t -> Tree t -> Maybe t

nodeAreSameNoJust :: (Eq a) => Tree (Maybe a) -> Tree (Maybe a) -> Maybe a

Alors, quel est le point clé ici ?Est-ce que ça veut dire quand je mets une variable avec le type a dans le nœud, la fonction ne générera pas de nœud de type a, donc il y a une erreur ?

Était-ce utile?

La solution

En fait, l'absence de Just fait pas rendez-le mal typé.

Voici l'affaire.Le code

nodeAreSame (Node a _ _) (Node b _ _)
            | a == b = a
nodeAreSame _ _ = Nothing

est bien typé à condition que a et b sont du type Maybe t pour certains t, puisque c'est le genre de Nothing.Ainsi, le système de types fait cette inférence.

Maintenant, quand vous avez un littéral numérique comme 3, on en déduit qu'il est du type Num s => s jusqu'à ce que vous le validiez réellement dans un type de données particulier (comme Int ou Double).

Ainsi, lorsqu’il met ces deux faits ensemble, il présume ce qui suit :

Num (Maybe t) => 3 :: Maybe t.

Comme il n'existe aucun exemple pour Num (Maybe t), il se plaint à ce moment-là, avant d'avoir l'occasion de se plaindre du fait que 3 :: Maybe t ça n'a aucun sens.

Autres conseils

À quoi d'autre vous attendriez-vous, simplement a?Cela ne marchera pas, parce que a et Nothing ne sont pas du même type.Toutes les définitions d'une fonction doivent renvoyer le même type. Nothing et Just a correspondent parce qu'ils sont tous les deux du type Maybe a.

Dans la version no Just, l'élément de l'arborescence doit être de type Peut-être a.

Je ne suis pas entièrement sûr que la raison pour laquelle l'erreur soit par exemple Num (Peut-être a).Je pense que l'erreur est plus éclairante si vous utilisez une chaîne au lieu du 3.

*Main> nodeAreSameNoJust (Node "arst" Empty Empty) (Node "arst" Empty Empty)
<interactive>:1:24:

Couldn't match expected type `Maybe a'
       against inferred type `[Char]'
In the first argument of `Node', namely `"arst"'
In the first argument of `nodeAreSameNoJust', namely
    `(Node "arst" Empty Empty)'
In the expression:
    nodeAreSameNoJust
      (Node "arst" Empty Empty) (Node "arst" Empty Empty)

Ici, il est plus clair qu'il attend quelque chose du type Maybe a.Dans les deux cas, le deuxième cas de la fonction est Nothing, donc le type de résultat est déduit être Maybe a.En incluant le Just, la valeur que vous utilisez dans l'arborescence est ensuite placée dans un type peut-être.Sans cela, il s'attend à ce que le résultat a soit du même type que Nothing, puisque chaque partie de la fonction doit être du même type.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top