1

I've tried implementing a recursive factorial function in GHCi, but I'm receiving the following error:

Prelude> fact n = n * fact (n-1)
Prelude> fact 0 = 1
Prelude> fact 1
*** Exception: <interactive>:2:1-10: Non-exhaustive patterns in function fact

Where is this coming from, and how can I avoid this mistake in the future?

t_d_milan
  • 55
  • 3
  • Does this still happen if you write it in a file/outside of GHCI? Nothing stands out to me. – Carcigenicate Dec 01 '16 at 05:44
  • 5
    There is a duplicate for this somewhere, but essentially you haven't provided two cases for a single `fact` function; GHCi 8 lets you drop the `let` from function definitions now, so you really defined one function defined for any argument, then *replaced* it with a function defined only for 0. – chepner Dec 01 '16 at 05:44
  • 3
    You probably wouldn't make this mistake in earlier versions of GHCi; an assignment without `let` would be an error, and you probably wouldn't mistake `let fact n = ...` followed by `let fact 0 = 1` as parts of the same definition. – chepner Dec 01 '16 at 05:50
  • 1
    @chepner, I think not *quite* a duplicate because of the syntax relaxation. – dfeuer Dec 01 '16 at 05:53
  • @dfeuer Yeah, I wanted to use the question where we've discussed GHC8 specifically, but I can't find it :/ – chepner Dec 01 '16 at 12:39

1 Answers1

7

As people have pointed out in the comments, a definition on a single line in GHCi 8 replaces any previous definition. If you want to enter a multi-pattern definition, you need to use the special :{ and :} codes to start and end a multi-line command. So, the following works fine:

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

(Note that this is applicable to GHCi 8 only, not 7.)

Also, mind the order in your definition. In Haskell, order of patterns matters, so if you try to match fact n first, it will always match, so your fact 0 pattern will never be used..

Edit: For GHCI 7, you need to use the let syntax with appropriate indentation to enter a multi-pattern definition:

Prelude> :{
Prelude| let fact 0 = 1
Prelude|     fact n = n * fact (n-1)
Prelude| :}
Prelude> fact 10
3628800
Prelude> 
K. A. Buhr
  • 45,621
  • 3
  • 45
  • 71
  • The multi-line syntax is the same. The improvement is that definitions don't need `let` anymore, which was especially obnoxious for multi-line definitions. – dfeuer Dec 01 '16 at 06:45