2009-05-05 8 views
4

Fondamentalement ce que je dois faire est d'écrire une fonction qui prend dans une liste de type [(String, String)] et imprime le contenu de sorte que, ligne par ligne, la sortie ressemble à ceci:Haskell: Imprimer le contenu d'une liste de tuples

FirstString : SecondString 

FirstString : SecondString 

..etc, pour chaque élément de la liste. J'ai le code suivant et il l'imprime, mais pour une raison quelconque, il imprime une ligne contenant [(),()] à la fin.

display :: Table -> IO() 
display zs = do { 
    xs <- sequence [putStrLn (a ++ " = " ++ b) | (a, b) <- zs]; 
    print xs 
} 

Y at-il quelque chose que je fais mal?

Répondre

10

L'impression finale xs est inutile. La séquence ici renvoie un tas de() s (la valeur de retour de putStrLn), et print l'imprime aussi.

Pendant que vous y êtes, maintenant que l'impression xs est parti, vous pouvez vous débarrasser de la liaison des variables xs et faire séquence dans sequence_ de jeter la valeur de retour, ce qui donne:

display :: Table -> IO() 
display zs = sequence_ [putStrLn (a++" = "++b) | (a,b) <- zs] 
+2

Si la mémoire est un problème, vous voudrez peut-être vérifier la méthode de newacct (ci-dessous). –

4

Ecrire une fonction qui prend un tuple à une chaîne, formatée comme vous le souhaitez.
Puis concatMap cette fonction sur votre liste; imprime le résultat.

8

Vous pouvez même utiliser mapM:

display :: Table -> IO() 
display = mapM_ (\(a,b) -> putStrLn (a++" = "++b)) 
+1

Cette méthode utilise moins de mémoire que la méthode de Bdonlan. Sur mes données d'échantillon, cette méthode a utilisé environ 70k de moins. Je me demande si la méthode de bdonlan utilise plus de mémoire car elle doit créer une liste d'actions d'E/S. –

+1

Comment mesurez-vous l'utilisation de la mémoire? Haskell crée un/lot/d'allocations éphémères, donc ce que cela signifie probablement, c'est que c'est tout simplement plus rapide :) – bdonlan

6

Je suis d'accord avec ja que vous devez diviser votre code pour deux fonctions:

  • A pur partie: une fonction qui prend votre structure de données et le transforme en une chaîne
  • impure partie, qui rend cette chaîne à la console

Voici une implémentation simple:

showTable :: Table -> String 
showTable xs = concatMap format xs 
    where 
    format (a, b) = a ++ " : " ++ b ++ "\n" 

display :: Table -> IO() 
display table = putStr (showTable table) 

Cette conception présente deux avantages:

D'une part, la plupart de votre `logique » est dans la partie pure du code, ce qui est agréable, dans une sorte de programmation fonctionnelle. Deuxièmement, et c'est juste un principe de génie logiciel simple; vous avez maintenant une fonction réutilisable que vous pouvez utiliser, si jamais vous voulez formater votre structure de données dans une autre partie de votre code (semble probable).

+1

ou faites partie de Table de classe Show, pour lequel vous pouvez faire: 'show myTable' – fengshaun