Question

J'ai un problème avec la portée de Haskell dans les définitions . Lorsque j'ai la fonction f suivante, où je souhaite transmettre le x à la fonction définie localement f1 sans l'utiliser explicitement en tant que paramètre, Un message d'erreur m'indique que le type de x est incompatible avec celui de la sortie de f1 , même si ce doit être identique:

f :: Eq a => a -> [a]
f x = f1 x
    where
        f1 :: Eq a => a -> [a]
        f1 y = [ x, y ]

L'erreur est la suivante:

    Couldn't match expected type `a1' against inferred type `a'
      `a1' is a rigid type variable bound by
           the type signature for `f1' at test.hs:4:11
      `a' is a rigid type variable bound by
          the type signature for `f' at test.hs:1:8
    In the expression: x
    In the expression: [x, y]
    In the definition of `f1': f1 y = [x, y]
Failed, modules loaded: none.

Lorsque je passe cependant le x en tant que paramètre supplémentaire, comme je l'ai fait dans le code suivant avec la fonction g , cela fonctionne correctement:

g :: Eq a => a -> [a]
g x = g1 x x
    where
        g1 :: Eq a => a -> a -> [a]
        g1 x y = [ x, y ]

Y a-t-il un moyen de rendre le type un dans f compatible avec le type a (ou a1 ) dans f1 ?

Était-ce utile?

La solution

Le problème avec votre code est la signature de type f1 de portée locale. Il spécifie que f1 peut prendre n'importe quel type

f1 :: Eq a = > un - > [a]

Même s’il s’agit d’une fonction locale, vous avez généralisé cette fonction pour pouvoir prendre un type qui n’existe pas dans f, quoi que cette fonction reçoive HAS comme source, la signature de type n’est donc pas nécessaire.

Supprimez simplement la signature de type f1.

Edit: Lisez mon message pour moi-même, c'est un peu flou. a in f1 est un type paramétré qui peut tout prendre, mais les arguments qui lui sont transmis sont déjà liés dans f. Donc, cette fonction ne peut recevoir que ce que sa fonction parent reçoit, la signature de type que vous lui donnez casse cette règle. J'espère que c'est un peu plus clair.

Autres conseils

Dave est juste en haut. Une autre façon de penser est que même si vos deux signatures de type font référence à la variable a , il ne s’agit pas en fait de la même variable de type. Dans la notation Haskell-prime, les deux signatures peuvent être écrites de manière plus explicite:

pour tous a. Eq a = > un - > [a]

ce qui signifie que pour les deux fonctions, ils peuvent accepter un argument de quelque type que ce soit (dans Eq). Ce n'est évidemment pas le cas ici. Dans Haskell 98 standard, la seule option consiste à renoncer à la signature de type pour f1 . Mais GHC (et d'autres?) Supporte lexical Variables de type ciblées . Pour que vous puissiez écrire

{-# LANGUAGE ScopedTypeVariables #-}

f :: forall a. Eq a => a -> [a]
f x = f1 x
    where
        f1 :: a -> [a]
        f1 y = [ x, y ]

et cela fonctionnerait bien.

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