Frage

Ich schrieb eine Haskell-Funktion, die die Fakultät von jeder Zahl in einer bestimmten Liste und druckt sie auf den Bildschirm berechnet.

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

Die Funktion funktioniert, aber ich die dritte Zeile ein bisschen verwirrend finden. Warum hat nicht der Compiler (GHC) berichtete über einen Fehler, da es keine „tun“ vor der „putStrLn“ (quasi?) Funktion? Wenn ich „do“ aus der 4. Zeile weglassen, wird ein Fehler erscheint als erwartet werden.

Ich bin ganz neu in Haskell und seine Wege, pardon mir so gefallen, wenn ich etwas gesagt allzu dumm.

War es hilfreich?

Lösung

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

ist eigentlich eine andere Art und Weise des Schreibens

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

, die wiederum Mittel

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

Die do Notation ist ein bequemer Weg, um diese Monaden Zusammenreihung, ohne diese andere hässliche Syntax.

Wenn Sie nur eine Anweisung innerhalb des do haben, dann Bespannen Sie nichts zusammen, und die do ist überflüssig.

Andere Tipps

Wenn Sie neu in Haskell, denken Sie an do ähnlich wie erforderlich Zahnspange nach if in einer C-ähnlichen Sprache:

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

do funktioniert auf die gleiche Art und Weise in Haskell.


Vielleicht wäre es zu Blick auf die Art von factPrint helfen, und dann Refactoring zu verwenden Mustervergleich:

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

Also, wenn factPrint IO () zurückkehrt, und die Art der putStrLn "" ist IO (), dann ist es vollkommen legal für factPrint [] gleich putStrLn "". Keine do erforderlich - in der Tat, die Sie gerade factPrint [] = return () sagen könnte, wenn Sie nicht die Newline wollen

.

do wird zusammen mehrere monadische Ausdrücke zu binden. Sie hat keine Auswirkung, wenn sie von nur einem einzigen Ausdruck gefolgt.

Für die, wenn sein wohlgeformt es nur notwendig ist, dass die damalige Klausel und die else-Klausel desselben Typen haben. Da beide Klauseln den Typ IO () haben, ist dies der Fall.

Das Schlüsselwort kann zur Sequenzierung verwendet wird, ein if-then-else in Haskell muss nicht ein do überhaupt enthält, wenn jeder Zweig eine einzelne Anweisung zB ist.

if a
  then b
  else c

Sie müssen die do in Ihrem Beispiel, wie Sie zwei Operationen auf dem anderen Zweig sequenzieren. Wenn Sie die do dann die factPrint(tail list) Aussage gilt als nicht Teil der Funktion und damit der Compiler beschwert sich auslassen, da es eine unerwartete Aussage gestoßen wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top