2017-02-02 2 views
1

Je sais que c'est un peu difficile mais je me demande pourquoi ça ne marche pas!Utilisez `seq` et imprimez en haskell

module Main where 

sillyDebug :: Int -> Int -> Int 
sillyDebug x y = 
    (print x) `seq` (x + y) 

main :: IO() 
main = do 
    print (sillyDebug 1 2) 

alors que son idéal est le même que

sillyDebug = (trace (show x) False) `seq` (x + y) 

Est-il lié à l'effet d'évaluation ou sur le côté paresseux haskell? https://hackhands.com/lazy-evaluation-works-haskell/

+1

Veuillez consulter http://stackoverflow.com/help/mcve. La plupart de vos importations ne sont pas pertinentes, ici. 'sillyIO' n'est défini nulle part. 'sillyDebug = (trace (show x) False) \' seq \ '(x + y)' ne compile même pas. Et décrivez le problème auquel vous êtes confronté. Qu'est-ce que vous attendiez? Qu'est ce que tu obtiens? – Jubobs

+0

Désolé, c'est de ma faute: 3 –

+1

Ce problème concerne la différence entre * évaluer * une expression et * exécuter * une action monadique, mais je pense qu'il vaut également la peine de faire une note sur 'seq'. '' '' 'seq' b'' ne force pas forcément l'évaluation de' a'. Il génère une dépendance entre thunks, donc * si * 'b' est évalué, alors' a' l'est aussi. '' print (snd (x 'seq'y, z))' 'n'évalue jamais' x' car il n'évalue jamais 'y'. –

Répondre

4

Evaluer simplement une action IO ne fait rien du tout. Vous pouvez penser à IO comme un très gros type de somme de toutes les choses secondaires possibles Haskell peut faire faire, même si elle n'est pas réellement mise en œuvre comme ça du tout. Quelque chose comme ceci:

data IO a where 
    PutStrLn :: String -> IO() 
    ReadFile :: FilePath -> IO String 
    ExitWith :: ExitCode -> IO a 
    ... 

L'un des IO constructeurs dans cette visualisation théorique serait un constructeur Sequence, avec une signature de type comme celui-ci:

Sequence :: IO a -> (a -> IO b) -> IO b 

Ce constructeur est utilisé pour mettre en œuvre >>= pour le IO type.

À l'intérieur de GHC est une fonction magique appelée magicallyExecuteIO avec le type IO a -> a, qui coordonne pour chaque action d'effectuer réellement son effet secondaire correspondant. (Incidemment, cette fonction est aussi parfois prononcée unsafePerformIO.) GHC appelle implicitement magicallyExecuteIO sur le résultat de la fonction main de votre programme, ainsi que sur les expressions écrites en GHCi.

Cependant, sans utiliser magicallyExecuteIO, l'évaluation d'un des constructeurs IO comme PutStrLn ne fait rien. Dans cette mise en œuvre, il serait tout simplement travailler comme tout autre constructeur de données:

ghci> Just (PutStrLn "hello!") 
Just (PutStrLn "hello!") :: Maybe (IO()) 

(. Je l'ai enveloppé avec Just pour empêcher GHCi d'exécuter l'action IO)

Bien sûr, IO réelle de GHC Type n'est pas implémenté de cette façon, mais c'est juste un détail d'implémentation. L'évaluation d'une valeur IO a ne provoque pas d'effet secondaire plus qu'une évaluation d'une valeur Maybe a. Seulement magicallyExecuteIO peut le faire.