2013-04-12 15 views
5

Sto imparando Haskell e sto avendo problemi con una funzione fattoriale di base da this tutorial.Il fattoriale base Haskell non sta uscendo?

Fondamentalmente, ho definito un fattoriale come tale:

Prelude> let factorial 0 = 1 
Prelude> let factorial n = n * factorial (n - 1) 

Il tipo di controlli fuori:

Prelude> :t factorial 
factorial :: Num a => a -> a 

che ha un senso. Tuttavia, il comportamento di questa funzione no. Il risultato è (interactive): out of memory indipendentemente dall'ingresso.

Prelude> factorial 5 
(interactive): out of memory 

Devo presumere questo è una chiamata ricorsiva infinita che porta a un errore di memoria, ma io non sono sicuro di quello che potrebbe essere la causa di esso. La stessa cosa accade con factorial 0, anche se ho esplicitamente dichiarato che si tratta di 1:

Prelude> factorial 0 
(interactive): out of memory 

Ora, ecco la parte strana: Se io definisco la funzione fattoriale in un file, funziona benissimo. Creo un file tesths.hs s.t .:

factorial 0 = 1 
factorial n = n * factorial (n - 1) 

Quindi, se torno a GHCI e correre :l tesths.hs, posso eseguire factorial 5 senza errori.

Cosa sta succedendo qui?

risposta

11

Sono state definite due funzioni, anziché una singola funzione con due casi. Prova gli stessi comandi con la prima esecuzione :set -Wall, e dovresti ottenere un avviso di ombreggiatura del nome. Per risolvere il problema, provare

let factorial 0 = 1; factorial n = n * factorial (n - 1) 

invece.

+0

Huh. Ha senso, suppongo. Questo è uno strano comportamento, comunque. – Zyerah

+3

Lo è. 'lascia ...' in ghci è davvero 'lascia ... in'. Questa non è l'unica cosa un po 'strana riguardo a ghci - un risultato è mostrato in modo diverso a seconda che sia di tipo 'Mostra a => a',' Mostra a => IO a', o 'IO()'. – ScootyPuff

+0

Questo ha un senso. Dipende dal tipo di input, che è necessario in quasi tutte le lingue – Zyerah

11

È inoltre possibile utilizzare la sintassi :{ ... :} a dare un contributo più righe:

Prelude> :{ 
Prelude| let factorial 0 = 1 
Prelude|  factorial n = n * factorial (n - 1) 
Prelude| :} 
Prelude> factorial 10 
3628800 
Prelude> 

Allo stesso modo, è possibile utilizzare la modalità multilinea e rientro con :set +m:

Prelude> :set +m 
Prelude> let factorial 0 = 1 
Prelude|  factorial n = n * factorial (n - 1) 
Prelude| 
Prelude> factorial 10 
3628800 
Prelude> 

Nota la riga vuota. È possibile disattivare la modalità multilinea con :unset +m.

Vedere Section 2.4.3 of the GHC User's Guide, "[Using GHCi with] Multiline input" per la documentazione su questa roba.

4

Nota che c'è questa bella one-liner, troppo:

let factorial n = product [1..n] 
+3

http://www.willamette.edu/~fruehr/haskell/evolution.html – leftaroundabout