Search code examples
functionhaskellmultilineread-eval-print-loopghci

Non exhaustive pattern in function in GHCi


I want to make a function that displays the last element of a list. This is my code:

ghci> let myLast :: [a] -> a
ghci> let myLast [] = error 
ghci> let myLast [x] = x
ghci> let myLast (x:xs) = myLast xs

And I get the following error:

***Exception: Non-exhaustive patterns in function myLast

I understood that you get this error when you're missing a case, but I think I have included all the possibilities. Any ideas?


Solution

  • If you use a let in each line, each definition will make a new function named myLast, shadowing all the previous definitions. So what you end up with is equivalent to

    GHCi> let myLast (x:xs) = myLast xs

    alone.

    What you probably want is to make a haskell file, say MyLast.hs, containing

    module MyLast where
    
    myLast :: [a] -> a
    myLast [] = error 
    myLast [x] = x
    myLast (x:xs) = myLast xs
    

    you can then load that file into GHCi with ghci MyLast.hs.

    The keyword let is only needed when you're already in GHCi (or, in some monad like IO, or in another function) and want to make a local definition. But then you must only use the let once, e.g.

    GHCi> let myLast :: [a]->a; myLast [] = error; myLast [x] = x; myLast (x:xs) = myLast xs

    or

    twiceLast :: [Int] -> [Int]
    twiceLast = let myLast [] = error 
                    myLast [x] = x
                    myLast (x:xs) = myLast xs
                in \xs -> 2 * last xs
    

    which I would, however, prefer to write as

    twiceLast = (2*) . myLast
     where myLast [] = error 
           myLast [x] = x
           myLast (x:xs) = myLast xs