2010-11-02 2 views
2

Je joue avec du code Haskell. J'ai défini deux fonctions:La chaîne associative de Haskell est déroutante

count :: [a] -> Int 
count []  = 0 
count (x:xs) = 1 + (count xs) 

-- 03. Write a function that computes the mean of a list, i.e., the sum of all 
-- elements in the list divided by its length. (You may need to use the 
-- fromIntegralfunction to convert the length of the list from an integer 
-- into a floating-point number.) 

-- I've guessed this type definition, but it's incorrect: 
-- listMean :: [a] -> Double 
-- The following is the same inferred by hgci 
listMean :: (Fractional a) => [a] -> a 
listMean lst = (foldl1 (+) lst)/(fromIntegral (count lst)) 

Pourquoi [a] -> Double n'est pas correct? Il semble que je donne à lst une liste générique de type a et que listMean renvoie un double. Qu'est-ce que je fais mal?

Merci, Alfredo

Répondre

20

Tout d'abord, listMean :: [a] -> Double dit que listMean est une fonction qui prend une liste de tout type a à une seule valeur Double.

Mais vous dépendez d'être en mesure d'appliquer (+) aux éléments de la liste (foldl1 (+)), qui exige que le type a soit une instance de Num, ce qui signifie que vous avez au moins:

listMean :: (Num a) => [a] -> b 

Vous appliquer également (/) à la valeur du type a résultant de l'opération foldl1. Pour ce faire, a doit non seulement être une instance de Num, mais de Fractional. L'application de cette exigence du type a donne la signature de type:

listMean :: (Fractional a) => [a] -> b 

Maintenant, qu'en est-il b? Eh bien, la signature pour (/) est (/) :: (Fractional a) => a -> a -> a. Ainsi, le résultat de listMean doit également être une instance de Fractional. En outre, il doit être la même instance de Fractional que celle contenue dans la liste: le type b est donc, en fait, le type a et la signature la plus générale de listMean est:

listMean :: (Fractional a) => [a] -> a 

C'est exactement ce que le compilateur inféré. Si vous voulez vous spécialiser cela pour Double, vous devez remplacer les deux occurrences de a avec Double:

listMean :: [Double] -> Double 

Ceci est parce que vous avez aucun opérateur là-dedans qui forcera une instance de Fractional dans un Double, donc à la fois l'entrée et la sortie à (/) doivent être de type Double.

+1

+1, très belle explication. –

+0

Parfait !! Merci beaucoup! –

Questions connexes