Muhd
Muhd

Reputation: 25556

Haskell: 99 Questions #1: first solution doesn't run in GHCi

The first problem is to write a function to get the last element in a list.

The first solution provided in the solutions section is:

myLast :: [a] -> a
myLast [x] = x
myLast (_:xs) = myLast xs

So in GHCi I did:

Prelude> let myLast [a] = a
Prelude> let myLast (_:xs) = myLast xs
Prelude> myLast [1,2,3]

Which gave me the exception:

*** Exception: <interactive>:12:5-29: Non-exhaustive patterns in function myLast

Why isn't this working?

Upvotes: 2

Views: 209

Answers (2)

chris
chris

Reputation: 5018

When you are using let in the interpreter, this is actually a let inside the IO monad, as for example in a do-block

do
  ...
  let x = ...
  ...

If you want to define a recursive function from inside ghci you can do

Prelude> :edit file.hs

Then the file file.hs will be opened in an editor (e.g., in linux the editor specified via the environment variable EDITOR will be chosen; in general you can set the used editor from inside ghci by :set editor editor-name; you can make this setting persistent by adding it to your ~/.ghci file). Enter your function definition there. Save the file. And then load it in ghci with

Prelude> :load file.hs

Now the definitions from file.hs will be in scope.

Upvotes: 3

Thomas M. DuBuisson
Thomas M. DuBuisson

Reputation: 64740

It isn't working because your use of let in GHCi is wrong.

let myLast [a] = a

This defines a function myLast that only operates on lists of one element.

let myLast (_:xs) = mylast xs

This defines a new function, myLast, over-shadowing the old and unrelated function from the line above. This new function throws an exception for any input (or fails to terminate).

You should enter:

:{
let myLast [x] = x
    myLast (_:xs) = myLast xs
:}

Or alternatively just enter your code in a file and not the repl. I highly suggest you avoid the repl for anything beyond one-line or interactive experimentation.

Upvotes: 5

Related Questions