Alors que getLine
est pas paresseux, getContents
est, et il peut être combiné avec des fonctions comme lines
et words
. Par conséquent, le programme suivant ne lit assez stdin pour obtenir (jusqu'à) trois entiers de la première ligne et imprimer leur somme:
main :: IO()
main = do contents <- getContents
let lns = lines contents
result = sum $ map read $ take 3 $ words $ head lns
print (result :: Integer)
Notez que, si vous modifiez le programme pour accéder aux lignes suivantes - pour par exemple, si vous avez ajouté:
putStrLn $ take 80 $ lns !! 1
au fond du programme pour imprimer les 80 premiers caractères de la deuxième ligne, le programme devrait terminer la lecture de la première ligne (et serait donc accrocher un peu entre les deux dernières lignes du programme) avant de traiter les 80 premiers caractères de la seconde. En d'autres termes, cette lecture de ligne paresseuse n'est utile que si vous avez besoin de lire le premier bit de la première ligne, si cela n'était pas évident pour vous - Haskell n'a aucun moyen magique de passer le reste de la première ligne pour arriver à la seconde. Enfin, notez que, pour le programme ci-dessus, s'il y a moins de trois entiers sur la première ligne, cela ne fera que sommer ces nombres et n'essaiera pas de lire après la première ligne (ce que je pense est ce que tu voulais). Si vous ne vous souciez pas vraiment des fins de ligne et que vous souhaitez simplement additionner les trois premiers chiffres du fichier, peu importe comment ils sont divisés en lignes, vous pouvez en diviser le contenu directement en mots comme suit:
main = do contents <- getContents
let result = sum $ map read $ take 3 $ words contents
print (result :: Integer)
Je pense que la bibliothèque 'getLine' et votre' getLine'' sont toutes les deux strictement strictes. Les actions d'E/S ne peuvent pas retourner paresseusement à moins d'utiliser une fonction 'dangereuse '- c'est ce que l'on appelle les' IO paresseux 'et doivent être manipulées avec précaution, puisque la lecture commencera plus tard à cause de la paresse. Lazy IO est (in) célèbre pour le débogage. Vous pouvez cependant utiliser une coutume stricte 'get3Ints' qui ne lit que la partie de la chaîne dont vous avez besoin. – chi
'getLine' doit être strict pour être correct, et comme chi dit que' getLine'' se comporte exactement de la même façon. Si 'getLine' était non-strict, alors les calculs purs que vous ferez plus tard causeraient des E/S, en réalisant plus de caractères à partir de l'entrée paresseuse. Ce serait un cauchemar quand vous considérez que d'autres E/S peuvent aussi se passer, en lisant aussi depuis stdin: quels personnages vont où sera extrêmement difficile à comprendre. – amalloy
Cf. [cette réponse] (https://codereview.stackexchange.com/a/120037/16551) pour en savoir un peu plus sur «IO» et la paresse. Si vous voulez un 'getLine' paresseux, il aura probablement besoin d'un type similaire à' IO (ListT IO Char) 'où' dataT m a = Nil | Cons a (m (ListT m a)) '(Vous pouvez aussi avoir' ListT IO String' au lieu de 'ListT IO Char' si vous lisez l'entrée en morceaux d'une longueur donnée pour être plus efficace). – gallais