I am new to both Haskell and programming. My question about binding in pattern-matched, recursive functions. For instance, suppose I have a function which checks whether a given list (x:xs) is a sublist of another list, (y:ys). My initial thought, following the examples in my textbook, was:
sublist [] ys = True
sublist xs [] = False
sublist (x:xs) (y:ys)
| x == y = sublist xs ys
| x /= y = sublist (x:xs) ys
This works on test data, e.g.,
sublist [1, 2, 3] [1, 2, 4, 1, 2, 3]
where I expected it to fail. I expect it to fail, since
sublist [1, 2, 3] [1, 2, 4, 1, 2, 3]
= sublist [2, 3] [2, 4, 1, 2, 3]
= sublist [3] [4, 1, 2, 3]
at which point, I thought, [3] = 3:[] will be matched with (x:xs) in sublist, and [4, 1, 2, 3] will be matched with (y:ys) in sublist. How, then, is sublist working?
Edit: Thanks to everyone here, I think I've solved my problem. As noted, I was ("subconsciously") wanting sublist to backtrack for me. Using the last answer (BMeph) posted as a guide, I decided to approach the problem differently, in order to solve the "binding problem," i.e., the "backtracking" problem.
subseq :: (Eq a) => [a] -> [a] -> Bool
subseq [] _ = True
subseq _ [] = False
subseq (x:xs) (y:ys) =
-- subseq' decides whether the list bound to (x:xs) = M is a prefix of the list
-- bound to L = (y:ys); it recurses through L and returns a Bool value. subseq
-- recurses through M and L, returning a disjunction of Bool
-- values. Each recursive call to subseq passes M and ys to subseq', which
-- decides whether M is a prefix of the **current list bound to ys**.
let subseq' :: (Eq a) => [a] -> [a] -> Bool
subseq' [] _ = True
subseq' _ [] = False
subseq' (x:xs) (y:ys) = (x == y) && subseq' xs ys
in subseq' (x:xs) (y:ys) || subseq (x:xs) ys
It is working because:
[3] is matched as x:xs as 3:[],
[4, 1, 2, 3] is matched as y:ys as 4:[1,2,3]
3/=4 so sublist (x:xs) ys is evaluated, which eventually is True
trace:
sublist [1, 2, 3] [1, 2, 4, 1, 2, 3]
= sublist [2, 3] [2, 4, 1, 2, 3]
= sublist [3] [4, 1, 2, 3]
= sublist [3] [1, 2, 3]
= sublist [3] [2, 3]
= sublist [3] [3]
= sublist [] [] = True
sublist [1, 2, 3] [1, 2, 4, 1, 2, 3]
= sublist [2, 3] [2, 4, 1, 2, 3]
= sublist [3] [4, 1, 2, 3]
= sublist [3] [4, 1, 2, 3]
= sublist (3:[]) (4:[1,2,3]) -- Since 3 /= 4, we take sublist (x:xs) ys
= sublist (3:[]) [1,2,3]
= sublist (3:[]) (1:[2,3])
= sublist (3:[]) [2,3]
= sublist (3:[]) (2:[3])
= sublist (3:[]) [3]
= sublist [] []
= True
sublist checks if heads of lists are equal. If yes, then it removes them and proceeds (sublist xs ys). If no, it removes head from the second list (sublist (x:xs) ys). This way it "finds" the following association:
1 2 3
| | |
| | \-----\
| | |
1 2 4 1 2 3
In other words, to check sublist [1,2,3] ys for some list ys it pops elements from ys as long as they are not 1. Then it pops elements as long as they are not 2. Then it pops elements as long as they are not 3. If [1,2,3] is exhausted, then it reports True; if ys is exhausted, it reports False.
Debug.Trace is your friend. With sublist instrumented as
sublist [] ys = trace ("A: [] " ++ show ys) True
sublist xs [] = trace ("B: " ++ (show xs) ++ " []") False
sublist (x:xs) (y:ys)
| x == y = trace (info "C" "==")
sublist xs ys
| x /= y = trace (info "D" "/=")
sublist (x:xs) ys
where info tag op =
tag ++ ": " ++ (show x) ++ " " ++ op ++ " " ++ (show y) ++
"; xs=" ++ (show xs) ++ ", ys=" ++ show ys
you see what's happening, namely that it's repeatedly throwing away the head of the second list until it finds a match:
*Main> sublist [1, 2, 3] [1, 2, 4, 1, 2, 3]
C: 1 == 1; xs=[2,3], ys=[2,4,1,2,3]
C: 2 == 2; xs=[3], ys=[4,1,2,3]
D: 3 /= 4; xs=[], ys=[1,2,3]
D: 3 /= 1; xs=[], ys=[2,3]
D: 3 /= 2; xs=[], ys=[3]
C: 3 == 3; xs=[], ys=[]
A: [] []
True
Another tool that will help you implement sublist correctly is Test.QuickCheck, a library that automatically creates test data for use in verifying properties that you specify.
For example, say you want sublist to treat xs and ys as sets and determine whether the former is a subset of the latter. We can use Data.Set to specify this property:
prop_subsetOf xs ys =
sublist xs ys == fromList xs `isSubsetOf` fromList ys
where types = (xs :: [Int], ys :: [Int])
This says sublist should be equivalent to the definition on the right. The prop_ prefix is a popular convention for naming test properties to be used with QuickCheck.
Running it also identifies a failure case:
*Main> quickCheck prop_subsetOf
*** Failed! Falsifiable (after 6 tests):
[0,0]
[0]
I think where you may be misunderstanding, is that (when you first wrote the function) you assumed that in your check x /= y = sublist (x:xs) ys you (sub-consciously?) assumed that the function would backtrack and re-do your function with the tail of the original second list, not the tail of whichever piece of the list you're using when it doesn't match.
One nice (and unsettling) thing about Haskell is just how ridiculously powerful it is.
For an example, here's how what you wanted should have looked:
sublist [] ys = True
sublist xs [] = False
sublist (x:xs) (y:ys) | x /= y = False
| otherwise = sublist xs ys || sublist (x:xs) ys
which will check for all of the pieces of the first list. The "official" definition for the function (look up "isInfixOf" in your documentation) has a few extra functions that basically means the same thing.
Here's another way write it, that looks more "explanatory" to my eyes:
sublist [] ys = True
sublist xs [] = False
sublist xs ys = (xs == take (length xs) ys) || sublist xs (tail ys)
YuppieNetworking and sdcwc have already explained how the matching works. So your sublist searches for a sublist in the same sense as subsequence (not necessarily the same items in a row, there can be anything in between).
I want to note that you can often avoid explicit recursion to remove unnecessary items from the front of the list with dropWhile. Also, I wanted to give an example how to check if two lists have the same prefixes (you need this to check if the second list contains items of the first one in a row).
The first example is similar to your function, it allows for items in between, but it uses dropWhile to remove items in front of ys:
-- Test:
-- map ("foo" `subListOf`) ["kungfoo", "f-o-o!", "bar"] == [True,True,False]
[] `subListOf` _ = True
(x:xs) `subListOf` ys =
let ys' = dropWhile (/= x) ys -- find the first x in ys
in case ys' of
(_:rest) -> xs `subListOf` rest
[] -> False
The second example looks for a "dense" sublist:
-- Test:
-- map ("foo" `denseSubListOf`) ["kungfoo!", "-f-o-o-"] == [True,False]
[] `denseSubListOf` _ = True
_ `denseSubListOf` [] = False
xs `denseSubListOf` ys =
let ps = zip xs ys in
(length ps == length xs && all (uncurry (==)) ps) -- same prefix of xs and ys
|| xs `denseSubListOf` (tail ys) -- or search further
Please note that to check that the second list contains all the first one in the beginning I compare elements pair by pair (I zip them together to do it).
It is easier to explain by example:
zip [1,2,3] [1,2,3,4,5] -- gives [(1,1), (2,2), (3,3)], 4 and 5 are truncated
uncurry (==) -- an equivalent of (\(a,b) -> a == b)
all -- gives True iff (uncurry (==)) is True for all pairs
length ps == length xs -- this is to ensue that the right list is long enough
Related
As title says, I'm not fully grasping how haskell interprets
1:[[]]
Why does it seem to do(1:[]):[] ?
E: I got this thought from:
part'::[a] -> [[a]]
part' [] = [[]]
part' (x:xs) = p ++ [x:ys | ys <- p]
where p = part' xs
Specifically from p ++ [x:ys | ys <- p]
E.g. for part'[1]: is my train of thoughts correct ?:
part'[1] = (part'[]) ++ [1:ys | ys <- part'[]]
--> = [[]] ++ [1:[[]]]
Hope this makes it clear.
It seems like you're misunderstanding the [... | ys <- p] syntax. In this case, ys is a stand-in for each element of the list p, not for the whole list. The equational reasoning in the last part of your question should be
part' [1] = (part' []) ++ [1:ys | ys <- p]
-- = [[]] ++ [1:ys | ys <- [[]]]
-- = [[]] ++ [1 : []]
-- = [[], [1]]
The [] in Haskell can be quite confusing.
The empty brackets [] by themselves are the constructor for an empty list. Usually this is explained by this alternative (isomorphic) list definition, where [] is called Nil and : is called Cons.
data List a
= Nil
| Cons a (List a)
Things don't exactly get easier when you consider that any finite list has Nil in the end. It's the only possible way to end the recursion, e.g.:
Cons 3 (Cons 4 (Cons 5 Nil))
or, equivalently:
3 : (4 : (5 : []))
Some confusion comes from this handy syntax, which expresses again the same:
[3, 4, 5]
Now someone might read [] as simply the empty list without any clue about Cons and Nil.
Yet there's more: In type signatures, you encounter things like [Int] or [a] which means List Int or List a, thus the brackets - again - express an entirely different thing.
There's the risk of a false intuition regarding the meaning of the brackets in Haskell and suddenly you have to think hard about the exact meaning of things like [1] and [[1]], or 1:[] and (1:[]):[].
Behold, the Lists:
[a,b,c] ++ [d,e,f] =
[a,b] ++ [c,d,e,f] =
[a] ++ [b,c,d,e,f] =
[] ++ [a,b,c,d,e,f] =
a : [b,c,d,e,f] =
a : b : [c,d,e,f] =
a : b : c : [d,e,f] =
a : b : c : d : [e,f] =
a : b : c : d : e : [f] =
a : b : c : d : e : f : [] =
[a,b,c,d,e,f] ++ [] =
[a,b,c,d,e] ++ [f] =
[a,b,c,d] ++ [e,f] =
[a,b,c] ++ [d,e,f]
and list comprehensions:
[[a, 0] | a <- [1,2,3]] =
[r | a <- [1,2,3], r <- [[a, 0]]] =
concatMap (\a -> [[a, 0]]) [1,2,3] =
[[1, 0]] ++ [[2, 0]] ++ [[3, 0]] =
[[1, 0], [2, 0], [3, 0]]
I want actually undestand what is happening in this code. Can someone tell me what it's the main idea. I get that is derivation of a polynom. But I don't know what derN xs 1 , derN xs (n+1) and derN xs 0 actually do
derN :: P -> Int -> P
derN [] n = []
derPolinom :: P -> P
derPolinom xs = derN xs 0
Maybe it would help to work through an example. It looks like you have a definition like type P = [Int], so I’ll assume that. Let’s take the polynomial 3x2 + 5x + 7, which would be represented in this scheme as [7, 5, 3].
To compute the derivative of this polynomial, we start with derPolynom:
derPolinom [7, 5, 3]
=
derN [7, 5, 3] 0
So we just call derN. We find the first case that matches:
derN (x:xs) 0 = derN xs 1
Then x is 7 and xs is [5, 3], so we substitute those values into the body:
derN [5, 3] 1
We’ve arrived at another call, so we find the case that matches:
derN (x:xs) n = [n * x] ++ derN xs (n+1)
This time, x is 5, xs is [3], and n is 1. Again substitute:
[1 * 5] ++ derN [3] (1 + 1)
=
[5] ++ derN [3] 2
Now we have another recursive call, which matches the same pattern, binding x = 3, xs = [], and n = 2:
[5] ++ ([2 * 3] ++ derN [] (2 + 1))
[5] ++ ([6] ++ derN [] 3)
Finally we’ve reached the base case of the recursion:
derN [] n = []
So we perform our last substitution:
[5] ++ ([6] ++ [])
Then reduce to get an answer of [5, 6], which represents the polynomial 6x + 5, which is indeed the derivative of 3x2 + 5x + 7.
You’ll notice that we’re only ever prepending single-element lists, so this line:
derN (x:xs) n = [n * x] ++ derN xs (n+1)
Could be simplified into this:
derN (x:xs) n = n * x : derN xs (n+1)
This whole function could also be written more simply using a higher-order function to avoid having to write out the recursion explicitly. We can use drop to remove the last coefficient and zipWith (*) [1..] to multiply each remaining number in the list by its 1-based index (which indicates the exponent).
derPolinom xs = zipWith (*) [1..] (drop 1 xs)
Those are recursive calls. For instance, derN (x:xs) 0 = derN xs 1 should be read as "The derivative of a polynom, with x as a free member and xs as other coefficients, is the same as derivative of a polynom with coefficients xs, starting with power 1".
This procedure takes the list of coefficients of a polynom and builds the list of coefficients of its derivative, recursively traversing from the lowest power to the highest.
I want to obtain a list of some of the rotations of the following string "I want to break free tonight". The constraint is that a rotation can not begin with the words "to" or "tonight". So the list of rotations is ["I want to break free today", "want to break free tonight I", "break free tonight I want to", "free tonight I want to break"].
I wrote the following functions:
rotate :: [l] -> [l]
rotate [] = []
rotate (x:xs) = (x:xs) ++ head(x:xs)
rotate1 :: [a] -> [[a]]
rotate1 xs = take (length xs) (iterate rotate xs)
main = do
print $ rotate1(words("I want to break free tonight"))
Running this code, I obtained all possible rotations, but they form a list of lists having elements like ["want", "I", "to", "break", "free", "tonight"] which is different from the string "want I to break free tonight". Also, I would want to see how I can drop the rotations that begin with the words "to", "tonight". I tried to use the filter function for the second part but I did not manage to solve the problem. Any help/hint is appreciated. I notice that I am a beginner in Haskell.
Running this code…
The code doesn't run. It has type errors.
First of all, let's fix the formatting so it's easier to read, and remove the extra parentheses
rotate :: [l] -> [l]
rotate [] = []
rotate (x:xs) = (x:xs) ++ head (x:xs)
rotate1 :: [a] -> [[a]]
rotate1 xs = take (length xs) (iterate rotate xs)
main = print $ rotate1 (words "I want to break free tonight")
This is weird:
rotate (x:xs) = (x:xs) ++ head (x:xs)
First of all, x:xs is the entire list, and x is the head of the list. For example, rotate [1, 2, 3] becomes:
rotate [1, 2, 3] = let x = 1
xs = [2, 3]
in (x:xs) ++ head (x:xs)
rotate [1, 2, 3] = (1:[2, 3]) ++ head (1:[2, 3])
rotate [1, 2, 3] = [1, 2, 3] ++ head [1, 2, 3]
rotate [1, 2, 3] = [1, 2, 3] ++ 1
-- type error
But ++ needs a list on both sides. What you probably want here is:
rotate (x:xs) = xs ++ [x]
Which gives us:
rotate [1, 2, 3] = let x = 1
xs = [2, 3]
in xs ++ [x]
rotate [1, 2, 3] = [2, 3] ++ [1]
rotate [1, 2, 3] = [2, 3, 1]
This is the same as:
rotate x = tail x ++ [head x]
For the rest of your problem… the filter should be straightforward since there is a filter function which does exactly what you need, and the unwords function turns lists of words back into strings.
You want the function intercalate :: [a] -> [[a]] -> [a] in Data.List.
From the hackage docs:
intercalate :: [a] -> [[a]] -> [a]
intercalate xs xss is equivalent to (concat (intersperse xs xss)). It
inserts the list xs in between the lists in xss and concatenates the
result.
In ghci
> import Data.List
> intercalate " " ["want", "I", "to", "break", "free", "tonight"]
> "want I to break free tonight"
I am writing a simple program to find whether a given list is a matrix or not:
is_matrix :: [[a]] -> Bool
is_matrix [[]] = False
is_matrix (x:xs)
| x == [] = is_matrix xs
| x == [a] = True
| length x == length (head xs) = is_matrix xs
| otherwise = False
But when i compile the is_matrix.hs file it produces the following error:
Prelude> :load is_matrix.hs
[1 of 1] Compiling Main ( is_matrix.hs, interpreted )
is_matrix.hs:5:11: Not in scope: `a'
Failed, modules loaded: none.
Prelude>
I have no idea as to why is this happening?
a is not a variable, it is a type in your definition, so you cannot write x == [a].
I suppose you want to check if x is a single element list. If so you could write the conditions like this
is_matrix :: [[a]] -> Bool
is_matrix [[]] = False
is_matrix ([]:xs) = is_matrix xs
is_matrix ([x]:xs) = True
is_matrix (x:xs)
| length x == length (head xs) = is_matrix xs
| otherwise = False
Note that when you use | for the conditions, the variables in the scope are used, new variables are not bound. On the opposite, when using function pattern matching, variables on the left hand side are bound to their match.
By the way, Haskell usually uses camelCase rather than snake_case.
I am not exactly sure, what are you trying to check with the expression x == [a], since [a] is a type "list of a's". Let's try to implement the function, using the matrix definition from Wiki:
A matrix is a rectangular array of numbers or other mathematical
objects, for which operations such as addition and multiplication are
defined.
So, all we need to check is that all rows in the matrix has the same size. Note, also, that there is a case for, so called, empty matrix:
In some contexts, such as computer algebra programs, it is useful to
consider a matrix with no rows or no columns, called an empty matrix.
is_matrix :: [[a]] -> Bool
-- Note, I removed the is_matrix [[]] = False condition
is_matrix (x:xs)
| null xs = True -- There are no more rows in sub-matrix - the answer is True
| length x == length (head xs) = is_matrix xs -- The same as in your version
| otherwise = False -- The same as in your version
This function produces the following output:
*Main> is_matrix [[]]
True
*Main> is_matrix [[1, 2, 3], [4, 5, 6]]
True
*Main> is_matrix [[1, 2, 3], [7], [4, 5, 6]]
This function could also be implemented in more natural way using map function (the question about implementation of allTheSame function):
*Main> let allTheSame xs = all (== head xs) (tail xs)
*Main> let isMatrix = allTheSame . map length
*Main> isMatrix [[]]
True
*Main> isMatrix [[1, 2, 3], [4, 5, 6]]
True
*Main> isMatrix [[1, 2, 3], [7], [4, 5, 6]]
False
I am overall confused, and looking for a very detailed and explanatory answer, of how this code works:
let xs = [1] ++ concatMap (\x -> [x+1,x*10]) xs in xs
How does concatMap know what to map and concat over?
I understand more basic examples:
let x = [1] ++ x
Here it gets evaluated like [1] ++ [1] ++ [1] ..
But I don't seem to understand the first example with concatMap. It just doesn't make sense to me. I can work with recursion frequently without problems. However, that one piece of code is very confusing.
Let's try a much simpler example:
let xs = 1 : xs in xs
OK, so xs points to a (:) node. The head-pointer from here points to 1, and the tail-pointer points to xs (i.e., back to itself). So this is either a circular list, or an infinite list. (Haskell regards the two as the same thing.) So far, so good.
Now, let's try a harder example:
let xs = 1 : map (+1) xs in xs
Do you know what this will do?
So xs points to a (:) node. The head-pointer points to 1. The tail-pointer points to the expression map (+1) xs, with xs pointing back to the top again.
If you try to "look at" the contents of this list, it will cause the map expression to start executing. The definition of map is
map f js =
case js of
k:ks -> (f k) : (map f ks)
[] -> []
So map looks at xs to see if it's [] or (:). As we know, it's (:). So the first pattern applies.
What this means is that the entire map (+1) xs expression gets overwritten with (:), with its head-pointer pointing to (+1) 1 and its tail-pointer pointing to map (+1) xs2 (with xs2 denoting a pointer to the tail of xs).
At this point, inspecting (+1) 1 turns it into 2. So now we basically have
xs = 1 : 2 : map (+1) xs2
^ |
|___________|
This cycle repeats as you examine the list. Critically, at every moment map is pointing to a node just before itself. If it ever caught up to itself, you would have a problem. But map only ever looks at nodes we've already calculated, so it's fine.
The net result, then, is xs = 1 : 2 : 3 : 4 : ...
If you can understand that, you ought to be able to understand your own more complicated example.
If you want to make your head hurt, try:
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
This is a standard Haskell incantation for spitting out the Fibonacci numbers in O(N) time (rather than O(N*N) as the more obvious recursion would give you).
Think of concatMap as a simple composition of concat and map (concat . map).
In this particular case, you are initializing xs with 1. Once you start running your map, it will lift the lambda to operate on 1 (the first position in the list) and create a list containing two values, 2 and 10. Concat just extracts those two values from that list and puts them naked in xs, concatenating them with the existing 1. At this point, xs contains 1, 2 and 10 (xs = [1,2,10]).
Now, xs contains 1, 2 and 10 and map will repeat the process (of course, starting from the second position in the list), now operating on 2 and creating a list containing 3 and 20 and a second list containing 11 and 100 when operating on 10 (third position in the list). Concat will now extract those 4 values and append them to the contents of xs. Now xs contains 1, 2, 10, 3, 20, 11 and 100 (xs = [1,2,10,3,20,11,100]).
And you can rinse and repeat, this time map operating on the fourth position in the list (and every subsequent position), and concat doing its work to remove the new list containers and place the values directly into the top level list. As you can see, this process will generate that infinite list.
Does this help?
First, what is concat? It concatenates lists, presented to it in a list:
concat [ [1], [2], [3] ] = [ 1, 2, 3 ]
concat [ [1], [2,22], [3] ] = [ 1, 2, 22, 3 ]
and so forth. What does map do? It transforms each element in a list it is presented with:
map (1+) [1, 2, 3] = [ 2, 3, 4 ]
map (:[]) [1, 2, 3] = [ [1], [2], [3] ]
map (\x-> [x+1, x*10]) [1, 2, 3] = [ [2,10], [3,20], [4,30] ]
But concatMap f xs is the same as concat (map f xs):
concatMap (\x-> [x+1, x*10]) [1, 2, 3]
= concat (map (\x-> [x+1, x*10]) [1, 2, 3])
= concat [ [2,10], [3,20], [4,30] ]
= [ 2,10, 3,20, 4,30 ]
But, it doesn't need to see the input list through to its end, in order to proceed, producing its elements one by one. This is because of Haskell's laziness. Simply,
concat [ [2,10], [3,20], [4,30] ]
= [ 2,10, 3,20, 4,30 ]
= [ 2,10] ++ concat [ [3,20], [4,30] ]
This means that actually,
concat xs == foldr (++) [] xs
-- concat [a,b,...,n] = a ++ (b ++ (... ++ (n++[])...))
and
concatMap f xs == foldr ((++).f) [] xs
-- concatMap f [a,b,...,n] = f a ++ (f b ++ (... ++ (f n++[])...))
so it does work incrementally. For your example,
let xs = [1] ++ concatMap (\x -> [x+1,x*10]) xs in xs
== let xs = [1] ++ foldr ((++).(\x -> [x+1,x*10])) [] xs in xs
== let xs = [1] ++ foldr (\x -> ([x+1,x*10] ++)) [] xs in xs
== let xs = [1] ++ foldr (\x r -> x+1 : x*10 : r) [] xs in xs
Which simply means: xs is a list, which contains 1, and then x+1 and x*10 for each element x in xs - from the start again. We could write this down also as
xs = 1 : [y | x <- xs, y <- [x+1, x*10]]
So for 1, 2 and 10 will be "appended" at list's end, then for 2, 3 and 20 will be produced, for 10 - 11 and 100, and so on:
xs = 1 a b c d e f g h ....
[2,10]=[a,b]
= 1 2 10 c d e f g h ....
[3,20]=[c,d]
= 1 2 10 3 20 e f g h ....
[11,100]=[e,f]
....
Of course this won't be evaluated on its own; the definition is "dormant" until used, e.g. to print the first 6 elements of xs:
Prelude> let xs = 1 : [y | x <- xs, y <- [x+1, x*10]]
Prelude> take 6 xs
[1,2,10,3,20,11]
As we can see, what's really been defined here is not an infinite list - there are no infinite things after all - but a process of calculating as much of its elements as might be needed.
Yet another way of writing this definition is
xs = 1 : next xs
where
next (x:xs) = x+1 : x*10 : next xs
where the computation's structure is seen yet clearer: next "looks back" into xs as it is being defined, first 1 notch back; then 2; then 3; etc. (because it produces two new list elements for each one it consumes; this definition is thus productive). This is characteristic of a "corecursive" definition. Its calculation proceeds as
take 6 xs
= take 6 xs where xs=1:next xs -- next looks 1 element back
= 1:take 5 xs1 where xs=1:xs1; xs1=next xs
= 1:take 5 xs1 where xs1=2:10:next xs1 -- 2 elements back
= 1:2:take 4 xs2 where xs1=2:xs2; xs2=10:next xs1
= 1:2:10:take 3 xs3 where xs1=2:xs2; xs2=10:xs3; xs3=next xs1
= 1:2:10:take 3 xs3 where xs2=10:xs3; xs3=3:20:next xs2 -- 3 elements
= 1:2:10:3:take 2 xs4 where xs2=10:xs3; xs3=3:xs4; xs4=20:next xs2
= 1:2:10:3:20:take 1 xs5 where xs2=10:xs3; xs3=3:xs4; xs4=20:xs5; xs5=next xs2
= 1:2:10:3:20:take 1 xs5 where xs3=3:xs4; xs4=20:xs5; xs5=11:100:next xs3 -- 4
....