2016-08-17 2 views
3

Je travaille par haskell book et j'ai compris que :sprint x est utilisé pour imprimer les éléments de x a été évalué et les éléments n'ont pas été (ceux qui ne sont pas sont exprimés par un '_').Comprendre comment: l'évaluation de sprint et de liste fonctionne dans haskell

L'un des exemples fournis dans le livre,

Prelude> let blah = enumFromTo 'a' 'z' 
Prelude> :sprint blah 
blah = _ 

Prelude> take 1 blah 
"a" 
Prelude> :sprint blah 
blah = 'a' : _ 

Pour tester avec une entrée différente je l'ai fait dans GHCi: -

prelude> let b = [1,2,3,4,5] 
prelude> :sprint b 
b = _ 
prelude> take 1 b 
[1] 
prelude> :sprint b 
b = _ 

Si pas la sortie de :sprint b dans la dernière commande être b = 1 : _ puisque nous évaluons seulement un élément de liste unique et un opérateur de contre lorsque vous utilisez la commande take 1 b ?? Mais il montre la sortie ci-dessus. Comment et pourquoi cela se passe-t-il? La sortie ne devrait-elle pas être similaire à la sortie de type String?

Edit: J'ai fait des expériences plus et a obtenu ce résultat: -

prelude> let b = [1..10] :: [Int] 
prelude> :sprint b 
b = _ 
prelude> take 3 b 
[1,2,3] 
prelude> :sprint b 
b = 1 : 2 : 3 : _ 

D'accord, mon estimation initiale est, il est à cause de la façon dont je suis la construction des deux listes? L'un utilise des plages et l'autre en indiquant explicitement ses éléments (qui à son tour crée la liste en utilisant le constructeur ':' récursivement sur ses éléments)

Répondre

6

Le comportement de :sprint peut être un peu difficile. Dans ce cas, regardez le type de x:

> :t x 
x :: Num t => [t] 

Parce qu'il est polymorphes, les valeurs réelles qui se produisent dépendent de l'instance spécifique de Num dont vous avez besoin. Ainsi, x se comporte plus comme une fonction qui produira la liste [1,2,3,4,5] quand il peut comprendre exactement quel type vous voulez que les éléments aient.

Maintenant, vous pourriez penser, « ok, je vais faire une liste qui ne sont pas polymorphes », vous essayez ceci:

> let x = [1,2,3,4,5 :: Int] 
> :t x 
x :: [Int] 
> :sprint x 
x = [1,2,3,4,5] 

Que diable? Si vous y réfléchissez, cela a du sens. Nous avons dit ghci explicitement ce que la liste est. Ce n'est pas comme si on pouvait l'évaluer et ensuite le réévaluer plus tard. (Ce serait du gaspillage de toute façon.) Mais nous allons voir ce qui se passe quand on essaie de mapper une fonction sur x:

> let y = map (+1) x 
> :sprint y 
y = _ 
> take 1 y 
[2] 
> :sprint y 
y = 2 : _ 

Tout comme prévu!

Espérons que ça aide. L'évaluation paresseuse est l'une des choses les plus difficiles à propos de Haskell (quand cela devient important).

+2

Il peut être utile d'ajouter que le premier problème disparaît si vous faites ': set -XMonomorphismRestriction'. Quelques exemples d'utilisation de ': sprint', par ex. Dans le livre * Parallel and Concurrent Haskell *, précéder l'utilisation par défaut '-XNoMonomorphismRestriction' à l'intérieur de ghci, et ainsi provoquer ce problème. Vous devriez probablement toujours l'éteindre, ou être implacable avec les signatures, avant de jouer avec ': sprint' – Michael

+0

dûment noté. Merci pour le conseil. –