Question

J'ai écrit une fonction Haskell qui calcule le factoriel de chaque numéro dans une liste donnée et il imprime à l'écran.

factPrint list =
if null list
    then putStrLn ""
    else do putStrLn ((show.fact.head) list)
        factPrint (tail list)

La fonction fonctionne, mais je trouve la troisième ligne un peu confus. Pourquoi pas le compilateur (GHC) a signalé une erreur sur elle car il n'y a pas de « faire » avant que la fonction « putStrLn » (quasi?)? Si je laisse de côté « faire » à partir de la 4ème ligne, une erreur apparaît comme prévu.

Je suis tout à fait nouveau pour Haskell et ses moyens, alors s'il vous plaît pardonnez-moi si je disais quelque chose trop stupide.

Était-ce utile?

La solution

do putStrLn ((show.fact.head) list)
   factPrint (tail list)

est en fait une autre façon d'écrire

putStrLn ((show.fact.head) list) >> factPrint (tail list)

qui, à son tour, des moyens

putStrLn ((show.fact.head) list) >>= \_ -> factPrint (tail list)

La notation do est un moyen pratique de corder ces monades ensemble, sans cette autre syntaxe laid.

Si vous avez une seule instruction à l'intérieur du do, alors vous n'êtes pas corder quoi que ce soit ensemble, et le do est redondant.

Autres conseils

Si vous êtes nouveau à Haskell, penser à do comme semblables aux appareils nécessaires après if dans un langage C comme:

if (condition)
  printf("a"); // braces not required
else {
  printf("b"); // braces required
  finish();
}

do fonctionne de la même manière Haskell.


Peut-être qu'il serait utile d'examiner le type de factPrint et factoriser ensuite utiliser la correspondance de motif:

factPrint :: [Int] -> IO ()
factPrint [] = putStrLn ""
factPrint list = do
  putStrLn (show.fact.head) list
  factPrint (tail list)

Donc, si factPrint retourne IO (), et le type de putStrLn "" est IO (), alors il est parfaitement légal pour factPrint [] à l'égalité putStrLn "". Pas do nécessaire -. En fait, vous pouvez simplement dire factPrint [] = return () si vous ne voulez pas le saut de ligne

do est utilisé pour lier plusieurs expressions monades ensemble. Il n'a pas d'effet quand il est suivi par une seule expression.

Pour le cas être bien formé, il est seulement nécessaire que l'époque article et l'autre article ont le même type. Étant donné que les deux clauses ont le type IO () tel est le cas.

Le mot-clé est utilisé pour do séquençage, un if-then-else dans Haskell ne doit pas contenir un do du tout si chaque branche est une instruction unique par exemple.

if a
  then b
  else c

Vous avez besoin du do dans votre exemple que vous séquencez deux opérations sur votre branche d'autre. Si vous omettez le do alors la déclaration de factPrint(tail list) est considéré comme ne pas faire partie de la fonction et donc le compilateur se plaint qu'il a rencontré une déclaration inattendue.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top