last, as you'd expect, gives you the last item in a list. It has a corresponding function
initthat gives you everything but the last item.
intersperseallows you to insert an element between each element (e.g.
init (intersperse 'a' "bnnn") => "banana". Similarly,
intercalateinserts the lists between lists and concatenates the results. For different arrangements of the items, there are two functions.
subsequencesgives you a list of all subsequences of the argument and
permuatationsgives all the possible permutations.
Prelude> subsequences "abc"
Prelude> permutations "abc"
To reduce lists to a single value there are many versions of the fold function (in Clojure there was just
foldlis the direct equivalent to reduce which reduces a list to a single binary operator.
foldl (+) 0 [1,2,3]is equivalent to (((0 + 1) + 2) + 3).
foldl1is a convenience method without the initial argument, that only applies to non-empty lists
foldlr1are right-associative so
foldr (+) 0 [1,2,3]evaluates to (0 + (1 + (2 + 3))).
The fold family of functions can be extremely powerful - I need to read "A tutorial on the universality and expressiveness of fold" [PDF]that explores this in more detail. Some example functions that operate on lists defined as folds in Haskell include
On a side note, there are strict versions of the foldl functions, that with a '. Why'd you need these? Haskell is lazy by default which can mean you build up a great big thunk (a pending calculation). This can be bad (for example, increased space requirements). By making a strict version you evaluate the values as they becomes available. This stops the huge think building up and can be more efficient. There's a good discussion of this here.
foldrdoesn't have a corresponding strict version, and looking at the expansion it's easy to see why - there's nothing to be lazy with as the first value you can evaluate is right at the end of the list!
unfoldris an interesting function. It can be considered the opposite of
foldras it is used to build up a list from a seed value. The first argument is a function that returns
Nothingif it's finished or
ais prepended to the list, and
bis used as the next element. For example we can generate the Fibonacci sequence:
fibonacci :: [Integer]
fibonacci = unfoldr (\[a,b] -> Just(a+b,[b,b+a])) [0,1]
Prelude> take 10 fibonacci
iteratecan be written as
iterate f == unfoldr (\x -> Just (x, f x)). Another paper to add to the reading list is "The under appreciated unfold".
dropare functions for getting prefixes and suffixes of (potentially) infinite lists.
splitAtdoes both at the same time, returning a tuple
(take n xs, drop n xs).
dropWhiletake or drop errors whilst some predicate holds. Putting these together we can write a function
groupNwhich groups elements into sublists of size N.
groupN :: [a] -> Int -> [[a]]
groupN  _ = 
groupN xs n = a : groupN b n where
(a,b) = splitAt n xs
Prelude> groupN [1..7] 2
The Haskell list library is very complete and there's definitely some new ideas for me to absorb there. In particular, understanding unfoldr and folding in more detail seems to be an important thing to do!