Question

J'ai une question assez générale sur le système de type de Haskell. Je suis en train de se familiariser avec elle, et je la fonction suivante:

getN :: Num a => a
getN = 5.0 :: Double

Quand je tente de compiler, je reçois l'erreur suivante:

Couldn't match expected type `a' against inferred type `Double'
  `a' is a rigid type variable bound by
      the type signature for `getN' at Perlin.hs:15:12
In the expression: 5.0 :: Double
In the definition of `getN': getN = 5.0 :: Double

Si je comprends bien, la fonction est mise en place pour « retour » d'un type dans la classe Num. Double est dans cette classe ( http://www.zvon.org/other/ haskell / Outputprelude / Num_c.html ), donc je me serais attendu à ce que ce serait correct de « retour » d'un double dans ce cas.

Quelqu'un peut-il expliquer s'il vous plaît?

Était-ce utile?

La solution

Une fonction Num a => a signature devrait travailler pour any type dans la Num de classe. La mise en œuvre de 5.0 :: Double fonctionne pour un de type, pas pour tous types de la classe, de sorte que le compilateur se plaint.

Un exemple d'une fonction générique serait:

square :: (Num a) => a -> a
square x = x * x

Cela fonctionne pour tout type qui est un Num. Il fonctionne en double, entiers et quels que soient les autres chiffres que vous souhaitez utiliser. A cause de cela, il peut avoir une signature de type générique qui nécessite que le paramètre à être en classe Num. (Type classe Num est nécessaire parce que la fonction utilise la multiplication avec *, qui y est définie)

Autres conseils

Pour ajouter à la réponse de STH: Haskell est pas orienté objet. Ce n'est pas vrai que Double est une sous-classe de Num, de sorte que vous ne pouvez pas retourner un Double si vous promets de retourner une valeur de Num polymorphes, comme vous pouvez, disons, Java.

Lorsque vous écrivez getN :: Num a => a vous promets de retourner une valeur qui est entièrement polymorphes dans la contrainte de Num. En effet, cela signifie que vous ne pouvez utiliser les fonctions de la classe de type Num, comme +, *, - et fromInteger.

Vérifiez existentiellement types .

Une façon de le résoudre serait de définir un nouveau type de données

data NumBox = forall n. Num n => NumBox n

Vous aurez besoin -XExistentialQuantification pour obtenir ce travail.

Maintenant, vous pouvez écrire quelque chose comme

getN :: NumBox
getN = NumBox (5.0 :: Double)

Vous pouvez également définir une liste NumBox comme

let n3 = [NumBox (4.0 :: Double), NumBox (1 :: Integer), NumBox (1 :: Int) ]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top