Talk:Haskell/Lists II

Currying
The same problem as described here in the section Higher-Order Functions and Types https://en.wikibooks.org/wiki/Talk:Haskell/Higher-order_functions

78.29.93.171 (discuss) 09:42, 24 February 2019 (UTC)

Solutions
I'm learning Haskell, so I decided to do the exercises on this page. -- 1. takeInt :: Integer -> [Integer] -> [Integer] takeInt 0 _ = [] takeInt m (n:ns) = n : takeInt (m-1) ns main = print (takeInt 4 [11,21,31,41,51,61])

-- 2. dropInt :: Integer -> [Integer] -> [Integer] dropInt 0 n = n dropInt m (n:ns) = dropInt (m-1) ns main = print (dropInt 3 [11,21,31,41,51])

-- 3. sumInt :: [Integer] -> Integer sumInt [] = 0 sumInt (n:ns) = n + (sumInt ns) main = print (sumInt [1..5])

-- 4. scanSum :: [Integer] -> [Integer] scanSum n = scanSum' n 0 scanSum' [] _ = [] scanSum' (n:ns) a = n+a : (scanSum' ns (n+a)) main = print (scanSum [2,3,4,5])

-- 5. diffs :: [Integer] -> [Integer] diffs [] = [] diffs (m:[]) = [] diffs (m:n:ns) = n-m : (diffs (n:ns)) main = print (diffs [3,5,6,8]) --Colonel panic 21:14, 31 January 2006 (UTC)

Maybe something like this is what the author was looking for, based on the hint:

-- 5. diffs' :: [Integer] -> [Integer] -> [Integer] diffs' _ [] = [] diffs' [] _ = [] diffs' (a:ax) (b:bx) = (b-a) : diffs' ax bx diffs :: [Integer] -> [Integer] diffs [] = [] diffs (a:ax) = diffs' (a:ax) ax

-- Fshahriar 23:44, 7 May 2006 (UTC)

I think it would be more intuitive to substract the second from first element, and so on. At least when I read "difference between adjacent elements" I immediatly thought that [3,5,6,8] should produce [-2,-1,-2], only the example clarifies that.

-- Moritz, 21 May 2007 (UTC)


 * Hi folks, would you maybe consider updating the solutions page to this module? Thanks -- Kowey 11:28, 21 May 2007 (UTC)

Alternate Solution for scanSum
There's a solution for creating scanSum with only one function. The trick is in the pattern matching - "(x:y:zs)" will match the first element in a set, the second element, and the remainder.

Aborting evaluation
The note about aborting evaluation is useful here, but it may be a good idea to also include it in an earlier chapter, where factorial is introduced. In that chapter, it mentions that you can get into an infinite loop by feeding in a negative number, but it doesn't tell you how to abort. Also, it may be a good idea to spell out the keypress, in the case that the reader doesn't know what "C-c" means. 65.201.194.91 23:13, 22 June 2007 (UTC)

head/tail
ghci gives an error on compiling your solution of the head/tail-based implementation of "lastOf":

lastOf :: [a] -> a lastOf [] = error "Empty list" lastOf ls = if (tail ls == []) then head ls  else lastOf ls

Error: Could not deduce (Eq a) from the context arising from a use of `==' at taken.hs:68:15-29 Possible fix: add (Eq a) to the context of the type signature for `lastOf' In the predicate expression: (tail ls) == [] In the expression: if (tail ls) == [] then head ls else lastOf ls   In the definition of `lastOf': lastOf ls = if (tail ls) == [] then head ls else lastOf ls

Before giving this solution, you should explain the expression Eq.

By the way there is an error in the last line; it should read: "else lastOf (tail ls)". The complete correct function would be:

lastEl2 :: Eq a => [a] -> a lastEl2 [] = error "empty list" lastEl2 ls = if (tail ls == []) then head ls   else lastEl2 (tail ls)


 * Well spotted... going to fix both of these issues. --Duplode (discuss • contribs) 15:00, 3 April 2012 (UTC)

Rewrite of list comprehensions section
As a newbie Haskeller I am following this book chapter by chapter. When I reached the list comprehensions subsection it kind of bothered me because:


 * Many of the examples and commentaries were distracting and only tangentially related to the main subject.
 * Some of the code examples relied on language features not yet covered at this point of the book.
 * As a whole, it made the list comprehensions look far more complicated than they actually are.

In order to alleviate these problems I performed a substantial rewrite of the section. Some details - and, crucially, good exercises - are still to be added, but the key changes are already in place. Since I am still a newbie, I feel it would be mandatory to have the changes discussed and reviewed by more experienced people, so I invite you all to do so. Thanks! --Duplode (talk) 18:47, 27 April 2010 (UTC)


 * Thanks, and much appreciated! On first glance, your edits sound great to me, but I'll check them in detail when I've got the time.
 * -- apfe&lambda;mus 18:43, 28 April 2010 (UTC)


 * Your changes to the list comprehensions are fine. Note, however, that list comprehensions are even more general, they also involve . For example, the following
 * lists all the Pythagorean triples with numbers smaller than 50.
 * lists all the Pythagorean triples with numbers smaller than 50.


 * Concerning the order of the list chapters, however, I recommend the following order for the different functions and concepts:
 * 1 - and [], head and tail
 * 2 - map, filter, [1..100] syntax
 * 3 - list comprehensions as a more readable syntax for map  and filter.
 * 4 - (++), concat
 * 5 - Defining recursive functions on lists, zip
 * 6 - sum, product, all, any; then show that they are special cases of fold
 * -- apfe&lambda;mus 14:16, 3 May 2010 (UTC)

Renaming to be more clear
This chapter covers generalized functions, currying, and mapping… Mostly, it is about how functions work and the concepts aren't all that list-specific. It could have a much more precise chapter title than "More about lists"Backfromquadrangle (discuss • contribs) 23:51, 25 April 2014 (UTC)
 * Possibly, but there are some subtle issues involved. While about half of the chapter is about lists, the more interesting parts are in the other half. On the other hand, the discussions about functions here aim at introducing  as a key function on lists, and not as a convenient example of something else. It's just that higher order functions are too important for their first example to be presented as a black box. There are deeper discussions of higher order functions, partial application and related matters in "More on Functions" and "Higher Order Functions"; however I do not see that as duplication, but as deliberate strategy (i.e. introducing a concept in a very elementary way and then later coming back to it with a deeper treatment). You will find that strategy is used for a few other themes in the book.
 * The peculiar status of "More About Lists" and "List Processing" (the latter, in my opinion, has an even worse name than this one) is in part due to historical reasons. In essence, they are a single chapter which was arbitrarily divided in two because it was too big. That is why there is no introductory paragraph in "List Processing". Furthermore, back in 2010 I swapped large amounts of text between the two chapters in order to eliminate circular dependencies between the topics. --Duplode (discuss • contribs) 07:51, 27 April 2014 (UTC)

Code in "Generalizing even further" is incorrect
The following code from this chapter causes an error in GHC. In the above code, multiplyList is a partially-applied version of applyToIntegers, meaning that it takes an argument of type [Integer] and returns a value of type [Integer]. Its type signature, however, states otherwise: that it takes two arguments, of type Integer and [Integer], respectively. GHCi complains about this as follows:

Couldn't match type `[Integer]' with `Integer' Expected type: Integer -> [Integer] -> [Integer] Actual type: [Integer] -> [Integer] In the return type of a call of `applyToIntegers'

The definition of multiplyList should be either of the following:

Which is better given the context of the lesson?

Since I don't think composition (.) is really discussed that much until the later chapter "Higher-order functions and Currying," your second suggestions seems better to me at this point in the tutorial. Another possible way to correct this, (which as a novice seems to flow best in my thought pattern but may not be idiomatic Haskell) is:


 * Thanks for the correction, it was meant to be as you two have written.  is the best phrasing at this point, both because it's better to wait for "Higher-order functions" to go full point-free and because in Haskell Basics/Elementary Haskell we avoid insisting much on syntactic variations, as they can distract away from the key points (so sections can wait till "More on functions"). As for the final question, personally I prefer   in actual code, and   when proving things. Duplode (discuss • contribs) 13:12, 4 July 2015 (UTC)