
On Sun, Aug 21, 2011 at 03:42:33PM +0200, Marc Chantreux wrote:
main = readFile "/etc/passwd" >>= mapM_ print . lines
hello, je suis désolé pour les autres messages (modification un peu hative de la conf. de mon mailer). La question était en fait: comment produire une liste paresseuse des lignes d'un fichier. J'aimmerais pouvoir décrire une fonction cat :: filePath -> [String] afin de pouvoir écrire des choses telles que mapM_ putStrLn $ filter (isInfixOf "root") $ cat "/etc/passwd" cordialement, marc

2011/8/21 Marc Chantreux
On Sun, Aug 21, 2011 at 03:42:33PM +0200, Marc Chantreux wrote:
main = readFile "/etc/passwd" >>= mapM_ print . lines
hello, Salut,
je suis désolé pour les autres messages (modification un peu hative de la conf. de mon mailer).
La question était en fait: comment produire une liste paresseuse des lignes d'un fichier. J'aimmerais pouvoir décrire une fonction
cat :: filePath -> [String]
Si la fonction «cat» a ce type alors elle ne peut faire aucun effet de bord. Sa seule donnée en entrée est le nom d'un fichier et comme on le sait on ne peut généralement pas déduire le contenu exacte d'un fichier étant donné son nom :) Tu cherches donc une fonction avec IO dans le type ou une variante permettant d'acceder au système de fichier. Un bon candidat semble être readFile (ou ses cousins getContents et hGetContents). La documentation mentione le fait que cette fonction lit paraisseusement le fichier, ce qui étant donné sont type est un peut étrange... readFile :: FilePath -> IO String En effet sont type nous dit que une fois le nom de fichier donné, readFile "/etc/passwd" est un "effet" qui va lire le fichier et "/etc/passwd" et renvoyé sont contenu. Il n'y a donc normalement qu'un seul effet. Enfin bon bref readFile triche un peut mais c'est normalement pas perceptible (malheureusement ça l'est), et l'on appelle cette technique le "Lazy IO". Donc si readFile est un bon candidat il nous reste à découper le contenue en une liste de lignes avec lines: lines :: String -> [String] cat :: FilePath -> IO [String] cat fp = do xs <- readFile fp return (lines fp) ou en plus court: cat :: FilePath -> IO [String] cat = fmap lines . readFile (fmap, (<$>), et liftM font la même chose.) Au final, un petit =<< et le tour est joué: mapM_ putStrLn . filter (isInfixOf "root") =<< cat "/etc/passwd" (Un autre remarque au passage isInfixOf est fait pour être utilisé en infix : "root" `isInfixOf` line) ou directement: mapM_ putStrLn . filter ("root" `isInfixOf`) . lines =<< readFile "/etc/passwd" ou aussi putStr . unlines . filter ("root" `isInfixOf`) . lines =<< readFile "/etc/passwd" Amuse toi bien! -- Nicolas Pouillard http://nicolaspouillard.fr
participants (2)
-
Marc Chantreux
-
Nicolas Pouillard