
I'm trying yet again to "get" Haskell. I'm reading Graham Hutton's book "Programming in Haskell", and am working on one of the exercises. Sounds easy enough: Make a function 'last' that returns the last element of a non-empty list. After struggling a while, I looked at the answer: last = head . reverse. I wish I had thought of that. But I kept trying to get my recursive version done, but I can't seem to make ghci happy. (Version 8.10.5, if you care). I wrote: last [] = [] (Yes, I know that's not a non-empty list, but I don't want ghci whining about non-exhaustive patterns). Then I added: last [x] = x And I checked the type: :t last last:: [a] -> [a] Yes, that looks right. There seems to be only one other case: 2 or more elements. So I wrote: last (x:y:xs) = last (y:xs) I ran it: Prelude> last [1,2] *** Exception: <interactive>:2:1-27: Non-exhaustive patterns in function last What the heck is the problem? I've covered every possible list, haven't I? Stranger yet, I check the type again: Prelude> :t last last :: [a] -> t The type has changed. And I don't understand what it means. What's the 't'? I'm sure this is a simple beginner error, but I'm really confused. I don't see how it isn't exhaustive, and I don't see why the 3rd clause (or whatever it's called) caused the type to change. Someone help, please.

Le 15/01/2022 à 15:32, Terry Phelps a écrit : ...
*last [] = [] * (Yes, I know that's not a non-empty list, but I don't want ghci whining about non-exhaustive patterns). Then I added:
*last [x] = x*
Please notice that these two clauses are type-incoherent, unless *x* is a list Jerzy Karczmarczuk -- L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast. https://www.avast.com/antivirus

You've covered 0 elements, 1 element, 3 or more elements, but not 2 elements.
On Sat, Jan 15, 2022 at 9:33 AM Terry Phelps
I'm trying yet again to "get" Haskell. I'm reading Graham Hutton's book "Programming in Haskell", and am working on one of the exercises. Sounds easy enough:
Make a function 'last' that returns the last element of a non-empty list.
After struggling a while, I looked at the answer: last = head . reverse. I wish I had thought of that. But I kept trying to get my recursive version done, but I can't seem to make ghci happy. (Version 8.10.5, if you care). I wrote:
last [] = [] (Yes, I know that's not a non-empty list, but I don't want ghci whining about non-exhaustive patterns). Then I added:
last [x] = x And I checked the type: :t last last:: [a] -> [a]
Yes, that looks right. There seems to be only one other case: 2 or more elements. So I wrote:
last (x:y:xs) = last (y:xs)
I ran it:
Prelude> last [1,2] *** Exception: <interactive>:2:1-27: Non-exhaustive patterns in function last
What the heck is the problem? I've covered every possible list, haven't I?
Stranger yet, I check the type again:
Prelude> :t last last :: [a] -> t
The type has changed. And I don't understand what it means. What's the 't'?
I'm sure this is a simple beginner error, but I'm really confused. I don't see how it isn't exhaustive, and I don't see why the 3rd clause (or whatever it's called) caused the type to change.
Someone help, please. _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- brandon s allbery kf8nh allbery.b@gmail.com

Actually, I'm going to correct that; I misread. I suspect your real
problem is you entered those on separate lines in ghci, and each one
redefines the previous one instead of augmenting it because ghci can't
know you're going to continue the definition. Either use multi-line
input mode (:{ and :}) or enter them all on one line with semicolons
in place of newlines.
On Sat, Jan 15, 2022 at 9:43 AM Brandon Allbery
You've covered 0 elements, 1 element, 3 or more elements, but not 2 elements.
On Sat, Jan 15, 2022 at 9:33 AM Terry Phelps
wrote: I'm trying yet again to "get" Haskell. I'm reading Graham Hutton's book "Programming in Haskell", and am working on one of the exercises. Sounds easy enough:
Make a function 'last' that returns the last element of a non-empty list.
After struggling a while, I looked at the answer: last = head . reverse. I wish I had thought of that. But I kept trying to get my recursive version done, but I can't seem to make ghci happy. (Version 8.10.5, if you care). I wrote:
last [] = [] (Yes, I know that's not a non-empty list, but I don't want ghci whining about non-exhaustive patterns). Then I added:
last [x] = x And I checked the type: :t last last:: [a] -> [a]
Yes, that looks right. There seems to be only one other case: 2 or more elements. So I wrote:
last (x:y:xs) = last (y:xs)
I ran it:
Prelude> last [1,2] *** Exception: <interactive>:2:1-27: Non-exhaustive patterns in function last
What the heck is the problem? I've covered every possible list, haven't I?
Stranger yet, I check the type again:
Prelude> :t last last :: [a] -> t
The type has changed. And I don't understand what it means. What's the 't'?
I'm sure this is a simple beginner error, but I'm really confused. I don't see how it isn't exhaustive, and I don't see why the 3rd clause (or whatever it's called) caused the type to change.
Someone help, please. _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- brandon s allbery kf8nh allbery.b@gmail.com
-- brandon s allbery kf8nh allbery.b@gmail.com

Le 15/01/2022 à 15:43, Brandon Allbery a écrit :
You've covered 0 elements, 1 element, 3 or more elements, but not 2 elements.
No, [1,2] === 1:(2:[]) But my own answer was incomplete. I suspect that there is a confusion because T.P. might hava a conflict between tha Prelude last and his own... Anyway, skip this : last [] = [] and change the name "last" to a private one. Jerzy Karczmarczuk -- L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast. https://www.avast.com/antivirus

On Sat, Jan 15, 2022 at 09:32:27AM -0500, Terry Phelps wrote:
last [] = [] (Yes, I know that's not a non-empty list, but I don't want ghci whining about non-exhaustive patterns). Then I added:
last [x] = x And I checked the type: :t last last:: [a] -> [a]
Yes, that looks right. There seems to be only one other case: 2 or more elements. So I wrote:
last (x:y:xs) = last (y:xs)
The first problem is that you've defined three different functions, each overriding the next Prelude> foo s = "Hello " ++ s Prelude> foo s = "Goodbye " ++ s Prelude> foo "Tom" "Goodbye Tom" I suggest putting the functions in a source file, say "test.hs" and then loading it in GHCi instead. I also suggest calling your function "mylast" because Prelude already exports a function called "last": % cat test.hs mylast [] = [] mylast [x] = x mylast (x:y:xs) = mylast (y:xs) % ghci ... Prelude> :l test.hs [1 of 1] Compiling Main ( test.hs, interpreted ) Ok, one module loaded. *Main> :t mylast mylast :: [[a]] -> [a] *Main> mylast [[1,2], [3,4]] [3,4] It kind of does what you want, but not quite. That's the next problem for you to solve! Good luck and enjoy. Tom

The definition last [] = [] was a bad move. Warnings about unhandled alternatives are only that, WARNINGS. Something like this is quite definitely wrong. We want last [1,2,3] ===> 3 but last [] = [] says that last can only return lists. It's OK to say "this is not defined". It's OK to say "this is an error case". It's not OK to make stuff up that does not fit. last [] = undefined last (x:xs) = last' x xs or last [] = error "last []" last (x:xs) = last' x xs let you assure the compiler (and your readers) that you *have* considered this case; you didn't just forget about it. They also do not constrain the result type in any way, so they don't interfere with the rest of the definition. The meaning of last' x xs is "last' x xs is the last element of [x]++xs" and you can figure that out for yourself with a simple case analysis on xs. A hint on reading exercises in functional programming books: "make a function F that ..." almost NEVER means "make a function F that ... without even thinking about introducing any helper functions." When defining last, introducing last' is OK. You can make it local if you want: last (x:xs) = last' x xs where last' x (y:ys) = ... last' x [] = ... last [] = error "last []" although you don't need to.
participants (5)
-
Brandon Allbery
-
Jerzy Karczmarczuk
-
Richard O'Keefe
-
Terry Phelps
-
Tom Ellis