For some reason partial function definitions in GHCi always lead to some issues so partially defined functions never work for me.
For example, if I do this in the source file:
factorial 1 = 1
factorial n = n * factorial(n - 1)
all works correctly. If I do the same in GHCi, I get a StackOverflow exception:
ghci> fact 1 = 1
ghci> fact n = n * fact(n - 1)
ghci> fact 5
*** Exception: stack overflow
Or if I define recursive list length function, all works fine if defined in the source file, but if I do it in GHCI, I get exception about a non-exhaustive pattern:
ghci> my_length [] = 0
ghci> my_length (x:xs) = 1 + my_length xs
ghci> my_length [1, 2, 3]
*** Exception: <interactive>:3:1-35: Non-exhaustive patterns in function my_length
Is there some trick to partial definitions in GHCi? The tutorial I'm following seems to think it should be possible.
tl;dr: don't wirte multi-line definitions in GHCi
When you write this
ghci> fact 1 = 1
ghci> fact n = n * fact(n - 1)
ghci> fact 5
the interpreter actually sees it as something like
ghci> let fact 1 = 1
ghci> let fact' n = n * fact' (n - 1)
ghci> fact' 5
(In old versions of GHCi you actually had to write out let
, which was relaxed at some point - a mistake in my opinion.)
The reason the disambiguation foo
vs foo'
is done is a) that it allows you to "change definitions" while trying out stuff. Say you previously defined foo x = x+1
, but further experiments show you actually want foo x = x+2
. Well, you can just write that and the old definition will get shadowed by it. ...
⎡ Side note: I tend to say this isn't really working great. The problem is that other definitions you've previously made based on the old foo
will still refer to that old one:
ghci> let foo x = x+1
ghci> let bar y = foo y - 1
ghci> bar 19
19
ghci> let foo x = x+2
ghci> bar 19
19
ghci> let bar y = foo y - 1
ghci> bar 19
20
⎣
...b) that the interpreter doesn't need to re-open definitions that could already have been complete. See, Haskell doesn't require that a definition is actually exhaustive; the line
ghci> let fact 1 = 1
is in principle a valid definition (albeit useless). It is good practice to make all definitions exhaustive and theoretically GHCi could simply wait until it is complete, but it doesn't do that.
What it does offer instead is the multiline mode, enabled thus:
ghci> :set +m
ghci> let fact 1 = 1
ghci| fact n = n * fact (n-1)
ghci|
ghci> fact 4
24
It also has a special :{
:}
syntax, but I would advise against using that.
Even multiline mode isn't working great, in particular it makes it awkward to go back with up-arrow and change a definition: you'll actually need to go through all the lines and enter them again in the right order.
Upshot: it's best to avoid making any big definitions in GHCi. Much better to put them in a .hs
source file and load that from GHCi.