Talk:Haskell/Lists III

Thanks for fixing the fold stuff
I hadn't realised that my understanding of folds was quite so broken.

I'm going to add one or two notes to your text though. We need to explain that " ' " is a valid character in an identifier, and I don't think we've introduced infinite lists yet.

Paul.

foldl' and foldl1'
We did not learn about libraries or modules yet, so I can't use the information about those functions. Importing seems more than Elementary or Basic Haskell. -- gerymate

Map exercises
Are there any answers for the map and scan exercises (in Haskell/Answers to exercises)? I looked through the answer guide using some searches (didn't read the whole thing so as not to spoil later problems), but couldn't find any keywords like Int or Integer. Anyway, here's what I came up with. --Gwern (contribs) 05:50, 16 February 2007 (UTC)

negatel :: [Integer] -> [Integer] negatel l = map (negate) l

factorsl :: [Integer] -> Integer factorsl [] = [] factorsl (l:ls) = factors l : factorsl ls

factors p = [ f | f <- [1..p], p `mod` f == 0 ]

negatell :: Integer -> Integer negatell [] = [] negatell (l:ls) = map (negate) l : negatell ls

factList :: Int -> [Int] factList n = scanl1 (*) [1..n]

WTF?
How come none of the fold examples have fold in them? Can't you give an example of fold in action? It's very confusing....I think this section needs a bit of work. It's not clear.

--90.198.153.194 17:11, 22 October 2007 (UTC)

Type Signatures
Could we please get type signatures for the example functions used? Especially the echoes example. I was very lost when I first read it, and I still don't know what the types would be. And I believe that was the first attempt at an explanation of Lambdas. Would have been nice to know what they were back in the Pattern Matching chapter when they were first mentioned.

Nonassociative folds?
I think that our examples and exercises on folds are impoverished in that the operators used are always associative (and usually even commutative). The difference between  and   is more than just the order of computation but can even affect the result. In general, only one will be correct.

Some possibilities:
 * Code  using a fold and  ; one way will work, while the other will return the original list. (This operator is associative but of course not commutative.)
 * Horner's method for evaluating polynomials; this could be extended to converting a string like  from hexadecimal. (This operator is not even associative.)

I can write these as exercises (and write their solutions), but maybe somebody has other or better ideas.

—Toby Bartels (talk) 21:17, 25 November 2008 (UTC)

Folds...
One of the exercises is to generate a fact-list.

My very first approach was

but this builds a list like [24,6,2,1]. The question would be:


 * 1) 1 Since factList(n-1) is obviously appended at the very end, how to change the code to append it at the beginning?
 * 2) 2 What are the risks of it?

add 1)

add 2) Instead of linear complexity, you have quadratic complexity: xs ++ ys takes linear time in the length of xs; (([1]++[2])++[3])++[4])++... appends to elements of length 1,2,3,etc, for a total of 1+2+3+...+n = n*(n+1)/2

Although I don't understand in details the thing with the quadratic, cause the opposite is as well a recursion and therefore the same formula applies? I have to confess that statement is from an IRC-session.

I have to admit to have no real clue where to put that kind of information (either ListProcessing, Solutions, Lists, etc.)


 * A few things to point out:
 * Your original solution is already quadratic. The uses of both  and   are linear in , and the solution performs those operations   times recursively. As a broader point, folds are meant to capture recursion patterns, so you should not need explicit recursion when you use   and friends.
 * would also make it quadratic, as explained in the answer to 2) that you mention. The recursion scheme may be in itself linear, but if the operation is also linear in the size of the input the whole thing becomes quadratic. In general it is a bad idea to reverse the order when building a list by replacing  with  . I don't recall whether we point that out explicitly in some chapter; it would be a good thing to do so.
 * The immediate solution to the problem is to use . I can't see a way to write it, or , as a simple fold without resorting to unpleasant tricks like using   or  . (Though that might just be lack of imagination from myself. I'm still puzzled :))
 * By the way, the solutions to the exercise which asks for implementations of  and   use ,   and   indiscriminately, which isn't good. I will try and tidy them up.
 * Duplode (discuss • contribs) 03:32, 13 April 2014 (UTC)

foldr on inifine lists
"As a rule of thumb, you should use foldr on lists that might be infinite" .. and your waiting time "might be infinite". Fixing that =)


 * The text does mean that, in all seriousness :) The point is that with  if the result is also infinite you can extract a finite segment of it in finite time. Compare   with  . I wonder if there is a way to make the text a little clearer without belabouring it, though. --Duplode (discuss • contribs) 12:07, 28 September 2015 (UTC)

Difference between Haskell foldr and JavaScript reduceRight
Okay! I've gone ahead and added in a new subsection for review called "Are foldl and foldr opposites?"

When I first encountered how foldr works, I really did think it was a bug. But now I see it's not that way at all. I'm hoping the new section will help other newcomers like me who might expect foldr to compute like reduceRight from JavaScript, where it doesn't.

I've put it right before the section titled "foldr1 and foldl1", because that's where I first got tripped up about all this.

Also, the word accumulator is a little misleading, it doesn't accumulate anything like in imperative languages (where it changes the variable.) But I've kept it because it's used throughout the chapter. Isn't there a better word for it, being a constant? How about "predicate", "premise", "base", or "basis?"

-Edit

Oh! in the solutions shows how accumulator can make sense, in that it appears as if it's gathering up the results. Pretty neat!

--נהאל (discuss • contribs) 23:17, 9 July 2017 (UTC)


 * The new section is helpful, as it tends to not be immediately clear what "left-to-right" and "right-to-left" mean in this discussion (by the way, it may be worth it to review how such terms are used throughout the chapter). I feel approaching it by putting less weight on the JavaScript comparison would work better -- while there might be a couple of exceptions lying around, in general the book tries to avoid relying too much on comparisons with other languages, both to establish things in Haskell's own terms and to lower the bar in terms of previous experience of readers. With that in mind, I have edited your text quite a bit. If you feel I cut out too much, feel free to reintegrate passages from your original text.


 * As for "accumulator", you got it. Another way of looking at it is that a function parameter and a mutable variable are two different means of accumulating a value, and it can make sense to call either an accumulator.


 * Duplode (discuss • contribs) 06:16, 12 July 2017 (UTC)


 * I'm glad it's helpful! I like your edit, it's much more to the point. I made another pass at it, hope you think it's alright! Also, I'm glad you kept the explicit parentheses part. That part was really helpful towards my understanding of foldr.


 * --נהאל (discuss • contribs) 22:12, 13 July 2017 (UTC)