-1

The Haskell Wikibook provides one

foldl1           :: (a -> a -> a) -> [a] -> a
foldl1 f (x:xs)  =  foldl f x xs
foldl1 _ []      =  error "Prelude.foldl1: empty list"

that doesnt work. I tried to compile this version of it:

myFoldl1           :: (a -> a -> a) -> [a] -> a
mFoldl1 f (x:xs)  =  myFoldl1 f x xs
myFoldl1 _ []      =  error "Prelude.foldl1: empty list

I first thought it was missing a case to end the fold and that there was a problem with the typing

foldl1 _ [x] = x
foldl1 f (x:xs)  =  foldl (f x) xs

But this wont work either. I think the type issue goes deeper, but I dont have a good enough grasp of Haskell to think further. Can someone help me out?

duplode
  • 33,731
  • 7
  • 79
  • 150
Tina
  • 17
  • 2
  • 5
    Define "doesn't work". Do you get a compile error or a runtime error, or does it simply fail to terminate? The code you've provided works perfectly well on my GHC. – Silvio Mayolo Nov 30 '16 at 17:39
  • With myFoldl1 I get a compile error "type error - unification would give infinte type" – Tina Nov 30 '16 at 17:43
  • Hm... that's very odd. Is that the full error message? If so, which compiler are you using? – Silvio Mayolo Nov 30 '16 at 17:44
  • I use hugs, I have never had any problems with it, are there any differences to GHC that could cause this error? – Tina Nov 30 '16 at 17:46
  • Sorry the full msg is "type error in application" term "x" type "a" doesnt match "[[a]->[b]]" because "unification woild give infinite type" – Tina Nov 30 '16 at 17:47
  • 2
    Hm... I'm not sure. I'm quite certain that first snippet of code is correct. Is there anything else you're doing that might be unusual? – Silvio Mayolo Nov 30 '16 at 17:49
  • 2
    What's `myFoldl1`? There's nothing in what you posted with that name. You should include the code your wrote that actually causes the error, instead of the code you think you copied correctly! – K. A. Buhr Nov 30 '16 at 17:51
  • @ Silvio Not sure ... I dont understand how it could be correct anyway, because of the missing end case (match on the singleton lost to terminate the fold). @K.A.Buhr Icopied the code and just changed the name, to not have to hide foldl1 – Tina Nov 30 '16 at 17:55
  • 1
    You just edited your post to be incorrect. Change that `foldl1` back to a `foldl` and see if it works. – Silvio Mayolo Nov 30 '16 at 17:59
  • You don't need a base case if your function is not recursive. "Icopied the code and just changed the name" You should still show us the version of your code that you're actually trying to compile. You might have accidentally changed more (for example you might have replaced `foldl` by `myFoldl1` as well - in fact that seems the most likely explanation, but we won't have to speculate about that if you post your actual code). – sepp2k Nov 30 '16 at 18:00
  • I added the code I tried to compile (on a different machine, which is why it was copied wrongly into this question) – Tina Nov 30 '16 at 18:07
  • The fact that the `foldl1` implementation doesn't mirror exactly the `foldr1` one does make for a mildly confusing example. Perhaps it would even be worth adding a remark about the difference to the Wikibook. – duplode Nov 30 '16 at 18:29

3 Answers3

6
mFoldl1 f (x:xs)  =  myFoldl1 f x xs

You've made two mistakes when renaming the function: First you misspelled the function name in the definition of the above case (mFoldl1 instead of myFoldl1) and secondly you replaced the call to foldl in the original with a recursive call to myFoldl1.

The correct version would be:

myFoldl1 f (x:xs) = foldl f x xs
sepp2k
  • 363,768
  • 54
  • 674
  • 675
  • Thx for you answer, I already explained in the other comments that I am posting this question on a different machine (a tablet, where I quickly make typos) and have to write evrything again. I tried to edit it but it always shows me oriiginal post? – Tina Nov 30 '16 at 18:15
  • 8
    @Tina Please don't do that. If you retype code (especially in a way that is prone to typos), you'll just get people wasting their time (and yours) by focussing on mistakes that aren't actually in your code. In the future just copy and paste the code from the machine that it's on once you're back in front of it (it's not like you'd need the answers before that anyway since they're not gonna be any use to you on your tablet). Either way I'd wager that at least the second mistake I mentioned actually exists in your real code as well. The corrected code I posted definitely works. – sepp2k Nov 30 '16 at 18:25
1

I too stumbled across the error in the wikibook, and found this entry.

The answers above seem to be wrong: they are not even of the right type.

foldl1 f [x]       = x
fold11 f [x,y]     = f x y
foldl1 f x:y:zs    = f (f x y) (foldl1 f zs)
foldl1 _ []        = error "foldl1 undefined on []"

does the job, I think. I hope there is something more elegant.

Veryrusty
  • 11
  • 1
0

Correction! Above works, but the original using a call to foldl is far better. The confusion arises with fonts that don't clearly distinguish "l" and "1"! To be clear

fold1 f (x:xs) = foldl f x xs

is the obvious and simple original.

Veryrusty
  • 11
  • 1