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
....
Related
This question already has answers here:
Generating integers in ascending order using a set of prime numbers
(4 answers)
Closed 4 years ago.
I am trying to generate a list of all multiples which can be represented by the form , where a, b, and c are whole numbers. I tried the following,
[ a * b * c | a <- map (2^) [0..], b <- map (3^) [0..], c <- map (5^) [0..] ]
but it only lists powers of 5 and never goes on to 2 or 3.
Edit: My apologies, it seems that I did not clarify the question enough. What I want is an ordered infinite list, and while I could sort a finite list, I feel as if there may be a solution that is more efficient.
The reason why there are only powers of 5 is that Haskell tries to evaluate every possible c for a = 2^0 and b = 3^0 and only when it is finished it goes for a = 2^0 and b = 3^1.
So this way you can only construct a finite list like this:
[ a * b * c | a <- map (2^) [0..n], b <- map (3^) [0..n], c <- map (5^) [0..n] ]
for a given n.
My first idea was starting from lists of powers of 2, 3 and 5, respectively:
p2 = iterate (2 *) 1
p3 = iterate (3 *) 1
p5 = iterate (5 *) 1
It's also easy to merge two sorted streams:
fuse [] ys = ys
fuse xs [] = xs
fuse xs#(x : xs') ys#(y : ys')
| x <= y = x : fuse xs' ys
| otherwise = y : fuse xs ys'
But then I got stuck because fuse p2 (fuse p3 p5) doesn't do anything useful. It only produces multiples of 2, or 3, or 5, never mixing factors.
I couldn't figure out a purely generative solution, so I added a bit of filtering in the form of a set accumulator. The algorithm (which is quite imperative) is:
Initialize the accumulator to {1}.
Find and remove the smallest element from the accumulator; call it n.
Emit n.
Add {2n, 3n, 5n} to the accumulator.
Go to #2 if you need more elements.
The accumulator is a set because this easily lets me find and extract the smallest element (I'm using it as a priority queue, basically). It also handles duplicates that arise from e.g. computing both 2 * 3 and 3 * 2.
Haskell implementation:
import qualified Data.Set as S
numbers :: [Integer]
numbers = go (S.singleton 1)
where
go acc = case S.deleteFindMin acc of
(n, ns) -> n : go (ns `S.union` S.fromDistinctAscList (map (n *) [2, 3, 5]))
This works, but there are things I don't like about it:
For every element we emit (n : ...), we add up to three new elements to the accumulator (ns `S.union` ... [2, 3, 5]). ("Up to three" because some of them may be duplicates that will be filtered out.)
That means numbers carries around a steadily growing data structure; the more elements we consume from numbers, the bigger the accumulator grows.
In that sense it's not a pure "streaming" algorithm. Even if we ignore the steadily growing numbers themselves, we need more memory and perform more computation the deeper we get into the sequence.
From your code:
[ a * b * c | a <- map (2^) [0..], b <- map (3^) [0..], c <- map (5^) [0..] ]
Since map (5^) [0..] is an infinite list, upon first iterations of a and b, it iterates over the said infinite list, which won't halt. That's why it is stuck at powers of 5.
Here is a solution apart from arithmetics. Note that map (2^) [0..], map (3^) [0..], and map (5^) [0..] are all lists sorted in ascending order. That means the usual merge operation is applicable:
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) = if x <= y then x : merge xs (y:ys) else y : merge (x:xs) ys
For convenience, let xs = map (2^) [0..]; let ys = map (3^) [0..]; let zs = map (5^) [0..].
To get multiples of 2 and 3, consider the following organization of said numbers:
1, 2, 4, 8, 16, ...
3, 6, 12, 24, 48, ...
9, 18, 36, 72, 144, ...
...
Judging by this, you might hope the following works:
let xys = foldr (merge . flip fmap xs . (*)) [] ys
But this doesn't work, because from the organization above, merge doesn't know which row contains the resulting head element, infinitely leaving it unevaluated. We know that the upper row contains said head element, so with following little tweak, it finally works:
let xys = foldr ((\(m:ms) ns -> m : merge ms ns) . flip fmap xs . (*)) [] ys
Do the same against zs, and here comes the desired list:
let xyzs = foldr ((\(m:ms) ns -> m : merge ms ns) . flip fmap xys . (*)) [] zs
Full code in summary:
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) = if x <= y then x : merge xs (y:ys) else y : merge (x:xs) ys
xyzs = let
xs = map (2^) [0..]
ys = map (3^) [0..]
zs = map (5^) [0..]
xys = foldr ((\(m:ms) ns -> m : merge ms ns) . flip fmap xs . (*)) [] ys
in foldr ((\(m:ms) ns -> m : merge ms ns) . flip fmap xys . (*)) [] zs
but it only lists powers of 5 and never goes on to 2 or 3.
Addressing only this bit.
To calculate numbers 2^a*3^0b*5^c you tried generating the triples (a,b,c), but got stuck producing those of the form (0,0,c). Which is why your numbers are all of the form 2^0*3^0*5^c, i.e. only powers of 5.
It's easier if you start with pairs. To produce all pairs (a,b) you can work along the diagonals of the form,
a+b = k
for each positivek. Each diagonal is easy to define,
diagonal k = [(k-x,x) | x <- [0..k]]
So to produce all pairs you'd just generate all diagonals for k<-[1..]. You want triples (a,b,c) though, but it's similar, just work along the planes,
a+b+c = k
To generate such planes just work along their diagonals,
triagonal k = [(k-x,b,c) | x <- [0..k], (b,c) <- diagonal x]
And there you go. Now just generate all 'triagonals' to get all possible triples,
triples = [triagonal k | k <- [0..]]
The other way to look at it is you wanted the numbers which are only divisible by 2,3 or 5. So check if each number starting from 1 satisfies this condition. If yes it is part of the list.
someList = [x| x<- [1..], isIncluded x]
where isIncluded is the function which decides whether x satisfies the above condition. To do this isIncluded divides the number first by 2 till it can not be divided any further by 2. Then same it does with new divided number for 3 and 5. It at ends there is 1 then we know this number is only divisible by 2,3 or 5 and nothing else.
This may not be the fastest way but still the simplest way.
isIncluded :: Int -> Bool
isIncluded n = if (powRemainder n 2 == 1) then True
else let q = powRemainder n 2
in if (powRemainder q 3 == 1) then True
else let p = powRemainder q 3
in if (powRemainder p 5 == 1) then True else False;
powRemainder is the function which takes number and base and returns the number which can not be further divided by base.
powRemainder :: Int -> Int -> Int
powRemainder 1 b = 1
powRemainder n b = if (n `mod` b) == 0 then powRemainder (n `div` b) b else n
with this when I run take 20 someList it returns [1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36].
As others already commented, your core does not work because it is analogous to the following imperative pseudocode:
for x in 0..infinity:
for y in 0..infinity:
for z in 0..infinity:
print (2^x * 3^y * 5^x)
The innermost for takes infinite time to execute, so the other two loops will never get past their first iteration. Consequently, x and y are both stuck to value 0.
This is a classic dovetailing problem: if we insist on trying all the values of z before taking the next y (or x), we get stuck on a subset of the intended outputs. We need a more "fair" way to choose the values of x,y,z so that we do not get stuck in such way: such techniques are known as "dovetailing".
Others have shown some dovetailing techniques. Here, I'll only mention the control-monad-omega package, which implements an easy to use dovetailing monad. The resulting code is very similar to the one posted in the OP.
import Control.Monad.Omega
powersOf235 :: [Integer]
powersOf235 = runOmega $ do
x <- each [0..]
y <- each [0..]
z <- each [0..]
return $ 2^x * 3^y * 5^z
I'm not exactly sure if I'm even supposed to ask more general, nonspecific questions on this platform, but I'm new to writing Haskell and writing code in general and an in-depth explanation would really be appreciated. I'm very used to the typical method of using loop systems in other languages, but as Haskell's variables are immutable, I've found recursion really difficult to wrap my head around. A few examples from the Haskell Wikibook include:
length xs = go 0 xs
where
go acc [] = acc
go acc (_:xs) = go (acc + 1) xs
zip [] _ = []
zip _ [] = []
zip (x:xs) (y:ys) = (x,y) : zip xs ys
[] !! _ = error "Index too large" -- An empty list has no elements.
(x:_) !! 0 = x
(x:xs) !! n = xs !! (n-1)
The first one is kind of self-explanatory, just writing a length function for strings from scratch. The second is like an index search that returns a char at a specified point, and the third I guess kind of transposes lists together.
Despite somewhat knowing what these pieces of code do, I'm having a lot of trouble wrapping my head around how they function. Any and all step-by-step analysis of how these things actually process would be GREATLY appreciated.
EDIT: Thank you all for the answers! I have yet to go through all of them thoroughly but after reading some this is exactly the kind of information I'm looking for. I don't have a lot of time to practice right now, finals soon and all, but during my break and decided to take another crack at recursion with this:
ood x
|rem x 2 == 1 = ood (x-1)
|x <= 0 = _
|otherwise = ood (x-2)
I wanted to attempt to make a small function that prints every odd number starting from x down to 1. Obviously it does not work; it simply only prints 1. I believe it does hit every odd number on the way down, it just does not display it's answers intermittently. If any one of you could take my own attempt at code and show me how to create a successful recursion function it would really help me a lot!
Let's look at how one might construct two of these.
zip
We'll start with zip. The purpose of zip is to "zip" two lists into one. The name comes from the analogy of zipping two sides of a zipper together. Here's an example of how it functions:
zip [1,2,3] ["a", "b", "c"]
= [(1,"a"), (2,"b"), (3,"c")]
The type signature of zip (which is typically the first thing you'd write) is
zip :: [a] -> [b] -> [(a, b)]
That is, it takes a list of elements of type a and a list of elements of type b and produces a list of pairs with one component of each type.
To construct this function, let's go for standard Haskell pattern matching. We have four cases:
The first list is [] and the second list is [].
The first list is [] and the second list is a cons (constructed using :).
The first list is a cons and the second list is [].
The first list is a cons and the second list is also a cons.
Let's work out each of these.
zip [] [] = ?
If you zip together two empty lists, you have no elements to work with, so surely you get the empty list.
zip [] [] = []
In the next case, we have
zip [] (y : ys) = ?
We have an element, y, of type b, but no element of type a to pair it with. So we can only construct the empty list.
zip [] (y : ys) = []
The same happens in the other asymmetrical case:
zip (x : xs) [] = []
Now we get to the interesting case of two conses:
zip (x : xs) (y : ys) = ?
We have elements of the right types, so we can make a pair, (x, y), of type (a, b). That's the head of the result. What's the tail of the result? Well, that's the result of zipping the two tails together.
zip (x : xs) (y : ys) = (x, y) : zip xs ys
Putting all these together, we get
zip [] [] = []
zip [] (y : ys) = []
zip (x : xs) [] = []
zip (x : xs) (y : ys) = (x, y) : zip xs ys
But the implementation you gave only has three cases! How's that? Look at what the first two cases have in common: the first list is empty. You can see that whenever the first list is empty, the result is empty. So you can combine these cases:
zip [] _ = []
zip (x : xs) [] = []
zip (x : xs) (y : ys) = (x, y) : zip xs ys
Now look at what's now the second case. We already know that the first list is a cons (because otherwise we'd have taken the first case), and we don't need to know anything more about its composition, so we can replace it with a wildcard:
zip [] _ = []
zip _ [] = []
zip (x : xs) (y : ys) = (x, y) : zip xs ys
That's produces the zip implementation you copied. Now it turns out that there's a different way to combine the patterns that I think explains itself a bit more clearly. Reorder the four patterns like this:
zip (x : xs) (y : ys) = (x, y) : zip xs ys
zip [] [] = []
zip [] (y : ys) = []
zip (x : xs) [] = []
Now you can see that the first pattern produces a cons and all the rest produce empty lists. So you can collapse all three of the rest, producing the nicely compact
zip (x : xs) (y : ys) = (x, y) : zip xs ys
zip _ _ = []
This explains what happens when both lists are conses, and what happens when that's not the case.
length
The naive way to implement length is very direct:
length :: [a] -> Int
length [] = 0
length (_ : xs) = 1 + length xs
This will give you correct answers, but it's inefficient. When evaluating the recursive call, the implementation needs to keep track of the fact that once it's done, it needs to add 1 to the result. In practice, it likely pushes the 1+ onto some sort of stack, makes the recursive call, pops the stack, and performs the addition. If the list has length n, the stack will reach size n. That's not great for efficiency. The solution, which the code you copied obscures somewhat, is to write a more general function instead.
-- | A number plus the length of a list
--
-- > lengthPlus n xs = n + length xs
lengthPlus :: Int -> [a] -> Int
-- n plus the length of an empty list
-- is n.
lengthPlus n [] = n
lengthPlus n (_ : xs) = ?
Well,
lengthPlus n (x : xs)
= -- the defining property of `lengthPlus`
n + length (x : xs)
= -- the naive definition of length
n + (1 + length xs)
= -- the associative law of addition
(n + 1) + length xs
= -- the defining property of lengthPlus, applied recursively
lengthPlus (n + 1) xs
So we get
lengthPlus n [] = n
lengthPlus n (_ : xs) = lengthPlus (n + 1) xs
Now the implementation can increment the counter argument on each recursive call instead of delaying them till afterwards. Well ... pretty much.
Thanks to Haskell's call-by-need semantics, this isn't guaranteed to run in constant memory. Suppose we call
lengthPlus 0 ["a","b"]
This reduces to the second case:
lengthPlus (0 + 1) ["b"]
But we haven't actually demanded the value of the sum. So the implementation could defer that addition work, creating a chain of deferrals that's just as bad as the stack seen earlier! In practice, the compiler is clever enough that it will work out how to do this right when optimizations are enabled. But if you don't want to rely on that, you can give it a hint:
lengthPlus n [] = n
lengthPlus n (_ : xs) = n `seq` lengthPlus (n + 1) xs
This tells the compiler that the integer argument actually has to be evaluated. As long as the compiler isn't being intentionally obtuse, it will be sure to evaluate it first, clearing up any deferred additions.
I'm not sure exactly which part you're confused by. Perhaps you're just overthinking this? Let's walk through zip slowly.
For arguments' sake, let's say we want to execute zip [1, 2, 3] ['A', 'B', 'C']. What do we do?
We have zip [1, 2, 3] ['A', 'B', 'C']. What now?
The first line ("equation") of the definition of zip says
zip [] _ = []
Is our first argument an empty list? No, it's [1, 2, 3]. OK, so skip this equation.
The second equation of zip says
zip _ [] = []
Is our second argument an empty list? No, it's ['A', 'B', 'C']. So ignore this equation too.
The last equation says
zip (x:xs) (y:ys) = (x, y) : zip xs ys
Is our first argument a non-empty list? Yes! It's [1, 2, 3]. So the first element becomes x, and the rest become xs: x = 1, xs = [2, 3].
Is our second argument a non-empty list? Again, yes: y = 'A', ys = ['B', 'C'].
OK, what do we do now? Well, what the right-hand size says. If I put in some extra brackets, the right-hand side basically says
(x, y) : (zip xs ys)
So we're constructing a new list, which starts with (x, y) (a 2-tuple) and continues with whatever zip xs ys is. So our output is (1, 'A') : ???.
What is the ??? part? Well, it's like we executed zip [2, 3] ['B', 'C']. Go back to the top, walk through again the same way as before. You'll find that this outputs (2, 'B') : ???.
Now we started with (1, 'A') : ???. If we replace that with the thing we just got, we now have (1, 'A') : (2, 'B') : ???.
Take this one step further and we have (1, 'A') : (2, 'B') : (3, 'C') : ???. Here the ??? part is now zip [] []. It should be clear that the first equation says this is [], so our final result is
(1, 'A') : (2, 'B') : (3, 'C') : []
which can also be written as
[(1, 'A'), (2, 'B'), (3, 'C')]
You probably already knew that was what the answer would eventually be. I hope now you can see how we get that answer.
If you understand what the three equations make zip do at each step, we can summarise the process like this:
zip [1, 2, 3] ['A', 'B', 'C']
(1, 'A') : (zip [2, 3] ['B', 'C'])
(1, 'A') : (2, 'B') : (zip [3] ['C'])
(1, 'A') : (2, 'B') : (3, 'C') : (zip [] [])
(1, 'A') : (2, 'B') : (3, 'C') : []
If you're still confused, try to put your finger on exactly what part confuses you. (Yeah, easier said than done...)
The key to recursion is to stop worrying about how your language provides support for recursion. You really only need to know three things, which I'll demonstrate using zip as the example.
How to solve the base case
The base case is zipping two lists when one is empty. In this case, we simply return an empty list.
zip _ [] = []
zip [] _ = []
How to break a problem into one (or more) simpler problem(s).
A non-empty list can be split into two parts, a head and a tail. The head is a single element; the tail is a (sub)list. To zip together two lists, we "zip" together the two heads using (,), and we zip together the two tails. Since the tails are both lists, we already have a way to zip them together: use zip!
(As a former professor of mine would say, "Trust your recursion".)
You might object that we can't call zip because we haven't finished defining it yet. But we aren't calling it yet; we are just saying that at some point in the future, when we call this function, the name zip will be bound to a function that zips two lists together, so we'll use that.
zip (x:xs) (y:ys) = let h = (x,y)
t = zip xs ys
in ...
How to put the pieces back together.
zip needs to return a list, and we have our head h and tail t of the new list. To put them together, just use (:):
zip (x:xs) (y:ys) = let h = (x,y)
t = zip xs ys
in h : t
Or more simply, zip (x:xs) (y:ys) = (x,y) : zip xs ys
When explaining recursion, it's usually simplest to start with the base case. However, the Haskell code is sometimes simpler if you can write the recursive case first, because it lets us simply the base case.
zip (x:xs) (y:ys) = (x,y) : zip xs ys
zip _ _ = [] -- If the first pattern match failed, at least one input is empty
Taking a step further back, let's introduce the only recursive function you'll ever need:
fix :: (a -> a) -> a
fix f = f (fix f)
fix computes the fixed point of its argument.
The fixed point of a function is the value that, when you apply the function, you get back the fixed point. For instance, the fixed point of the square function square x = x**2 is 1, since square 1 == 1*1 == 1.
fix doesn't look terribly useful, though, since it looks like it just gets stuck in an infinite loop:
fix f = f (fix f) = f (f (fix f)) = f (f (f (fix f))) = ...
However, as we'll see, laziness lets us take advantage of this infinite stream of calls to f.
Ok, how do we actually make use of fix? Consider this nonrecursive version of zip:
zip' :: ([a] -> [b] -> [(a,b)]) -> [a] -> [b] -> [(a,b)]
zip' f (x:xs) (y:ys) = (x,y) : f xs ys
zip' _ _ _ = []
Given two nonempty lists, zip' zips them together by using the help function f that it receives to zip the tails of its inputs. If either input list is empty, it ignores f and returns an empty list. Basically, we've left the hard work to whoever calls zip'. We'll trust them to provide an appropriate f.
But how do we call zip'? What argument can we pass? This is where fix comes in. Look at the type of zip' again, but this time make the substitution t ~ [a] -> [b] -> [(a,b)]:
zip' :: ([a] -> [b] -> [(a,b)]) -> [a] -> [b] -> [(a,b)]
:: t -> t
Hey, that's the type fix expects! What's the type of fix zip'?
> :t fix zip'
fix zip' :: [a] -> [b] -> [(a, b)]
As expected. So what happens if we pass zip' its own fixed point? We should get back... the fixed point, that is, fix zip' and zip' (fix zip') should be the same function. We still don't really know what the fixed point of zip' is, but just for kicks, what happens if we try to call it?
> (fix zip') [1,2] ['a','b']
[(1,'a'),(2,'b')]
It sure looks like we just found a definition of zip! But how? Let's use equational reasoning to figure out what just happened.
(fix zip') [1,2] ['a','b']
== (zip' (fix zip')) [1,2] ['a','b'] -- def'n of fix
== (1,'a') : (fix zip') [2] ['b'] -- def'n of zip'
== (1,'a') : (zip' (fix zip')) [2] ['b'] -- def'n of fix, but in the other direction
== (1,'a') : ((2,'b') : (fix zip') [] []) -- def'n of zip'
== (1,'a') : ((2,'b') : zip' (fix zip') [] []) -- def'n of fix
== (1,'a') : ((2,'b') : []) -- def'n of zip'
Because Haskell is lazy, the last call to zip' doesn't need to evaluate fix zip', because its value is never used. So fix f doesn't need to terminate; it just needs to provide another call to f on demand.
And in then end, we see that our recursive function zip is simply the fixed point of the nonrecursive function zip':
fix f = f (fix f)
zip' f (x:xs) (y:ys) = (x,y) : f xs ys
zip' _ _ _ = []
zip = fix zip'
Let's briefly use fix to define length and (!!) as well.
length xs = fix go' 0 xs
where go' _ acc [] = acc
go' f acc (_:xs) = f (acc + 1) xs
xs !! n = fix (!!!) xs n
where (!!!) _ [] _ = error "Too big"
(!!!) _ (x:_) 0 = x
(!!!) f (x:xs) n = f xs (n-1)
And in general, a recursive function is just the fixed point of a suitable nonrecursive function. Note that not all functions have a fixed point, though. Consider
incr x = x + 1
If you try to call its fixed point, you get
(fix incr) 1 = (incr (fix incr)) 1
= (incr (incr (fix incr))) 1
= ...
Since incr always needs its first argument, the attempt to calculate its fixed point always diverges. It should be obvious that incr has no fixed point, because there is no number x for which x == x + 1.
Here’s a nice trick to show how to convert normal imperative loops into recursion. Here are the steps:
Make data immutable by not mutating objects (e.g. no x.y = z, only x = x { y = z })
Make variables “nearly immutable” by moving all variable-changes to just before control flow
Change into “goto form”
Work out the set of mutating variables
Add “variable changes” for mutating variables that don’t change at each goto
Replace labels with functions and goto with function (tail) calls
Here is a simple example after step 1 but before anything else (made up syntax)
let sumOfList f list =
total = 0
done = False
while (not done) {
case list of
[] -> done = True
(x : xs) ->
list = xs
total = total + (f x)
}
total
Well this doesn’t really do much other than change variables but there’s one thing we can do for step 2:
let sumOfList f list =
total = 0
done = False
while (not done) {
case list of
[] -> done = True
(x : xs) ->
let y = f x in
list = xs
total = total + y
}
total
Step 3:
let sumOfList f list =
total = 0
done = False
loop:
if not done then goto body else goto finish
body:
case list of
[] ->
done = True
goto loop
(x : xs) ->
let y = f x in
list = xs
total = total + y
goto loop
finish:
total
Step 4: the mutating variables are done, list, and total
Step 5:
let sumOfList f list =
done = False
list = list
total = 0
goto loop
loop:
if not done then
total = total
done = done
list = list
goto body
else
total = total
done = done
list = list
goto finish
body:
case list of
[] ->
done = True
total = total
list = list
goto loop
(x : xs) ->
let y = f x in
done = done
total = total + y
list = xs
goto loop
finish:
total
Step 6:
let sumOfList f list = loop False list 0 where
loop done list total =
if not done
then body done list total
else finish done list total
body done list total =
case list of
[] -> loop True list total
(x : xs) -> let y = f x in loop done list (total + y)
finish done list total = total
We can now clean things up by removing some unused parameters:
let sumOfList f list = loop False list 0 where
loop done list total =
if not done
then body done list total
else finish total
body done list total =
case list of
[] -> loop True list total
(x : xs) -> let y = f x in loop done list (total + y)
finish total = total
And realising that in body done is always False and inlining loop and finish
let sumOfList f list = body list 0 where
body list total =
case list of
[] -> total
(x : xs) -> let y = f x in body list (total + y)
And now we can pull the case into multiple function definitions:
let sumOfList f list = body list 0 where
body [] total = total
body (x : xs) total =
let y = f x in body list (total + y)
Now inline the definition of y and give body a better name:
let sumOfList f list = go list 0 where
go [] total = total
go (x : xs) total = go list (total + f y)
A loop is a function call is a loop. Reentering a loop body with updated loop parameters is the same as reentering a function body in a new recursive call with the updated function parameters. Or in other words, a function call is a goto, and the function name is the label to jump to:
loop_label:
do stuff updating a, b, c,
go loop_label
is
loop a b c =
let a2 = {- .... a ... b ... c ... -}
b2 = {- .... a ... b ... c ... -}
c2 = {- .... a ... b ... c ... -}
in
loop a2 b2 c2
You did say you're comfortable with loops.
Let's give the translations of your example functions in terms of the more primitive construct, case, as defined in the Report:
length xs = go 0 xs
where
go a b = case (a , b) of
( acc , [] ) -> acc
( acc , (_ : xs) ) -> go (acc + 1) xs
so it's the same old plain linear recursion.
Same goes to the other two definitions:
zip a b = case ( a , b ) of
( [] , _ ) -> []
( _ , [] ) -> []
(x : xs , y : ys) -> (x,y) : zip xs ys
(the last one is left as an exercise).
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.
Data.Lists.Split is actually not working winHugs interpreter. which can be get by splitEvery 3 ['a'..'z'] function
is it possible to achieve this without Data.Lists.Split ?
list of separate integers [5,5,5,6,6,6] -> to be [555,666] to concat every three numbers !
should be [Int]->[Int]
Yes, it's quite possible. You can proceed like this:
First write a function that takes three digits and "concat"s them into one number (this is quite easy using multiplication and addition).
Then you write another function which takes a list and processes its elements in threes using the previous function. Basically the definition of that function will look like the definition of map, except that you process three elements instead of one in the non-empty case (i.e. you use a pattern like x1:x2:x3:xs), and you call the previously defined function instead of one given as an argument.
Here's an implementation of splitEvery that should work for your purposes:
import Data.List
splitEvery _ [] = []
splitEvery n xs = chunk : splitEvery n remaining
where (chunk, remaining) = splitAt n xs
Let's make a general function that groups a given number of items, and applies a given function to each group.
groupMap :: ([a] -> b) -> Int -> [a] -> [b]
groupMap f n xs = go xs
where go [] = []
go xs = f (take n xs) : go (drop n xs)
OK, now what f should we pass in?
intListToInt :: [Int] -> Int
intListToInt xs = go xs 0
where go [] v = v
go (x:xs) v = go xs (x + v*10)
There are various different ways you could write this; I'm experimenting with the workhorse helper technique. Note that this type signature lines up nicely with the first argument of groupMap. Anyways...let's see if it works!
ghci> groupMap intListToInt 3 [5,5,5,6,6,6]
[555,666]
Yay! It even works for other stuff too. (some sketchy uses follow...)
ghci> groupMap (read :: String -> Int) 5 "1234554321"
[12345,54321]
ghci> groupMap (read :: String -> Bool) 4 "TrueTrueTrue"
[True,True,True]
ghci> groupMap sum 2 [1,2,3,4,5,6]
[3,7,11]
NB: If I'm not mistaken, intListToInt could benefit from a little more strictness:
{-# LANGUAGE BangPatterns #-}
intListToInt xs = go xs 0
where go [] !v = v
go (x:xs) !v = go xs (x + v*10)
Though I'm not at all familiar with which language pragmas Hugs supports.
Use show, concat and read:
map (read . (>>= show)) . splitEvery 3
Possible Solution:
Here is one possible solution, using only function from the Prelude:
group3 :: [Int] -> [Int]
group3 [] = []
group3 xs = toSingleNum (take 3 xs): (group3 (drop 3 xs))
where toSingleNum ys = read $ concat $ map show ys
There are, of course, innumerable ways to do this. This is one.
Explanation:
group3 works by using the take and drop functions and natural recursion to split the list into groups of 3, and applying toSingleNum to each of the groups.
Ignoring the application of take and drop, the function works roughly as below:
group3 [1,2,3,4,5,6,7,8,9]
toSingleNum [1,2,3] : group3 [4,5,6,7,8,9]
toSingleNum [1,2,3] : toSingleNum [4,5,6] : group3 [7,8,9]
toSingleNum [1,2,3] : toSingleNum [4,5,6] : toSingleNum [7,8,9] : group3 []
toSingleNum [1,2,3] : toSingleNum [4,5,6] : toSingleNum [7,8,9] : []
After toSingleNum is applied, we'd have:
123 : 456 : 789 : []
[123, 456, 789]
toSingleNum converts a list of numbers into a single number.
toSingleNum [1, 3, 4]
>>> 134
toSingleNum [12, 13, 14]
>>> 121314
The conversion in toSingleNum is done by converting the numbers to a String, then combining them, then converting back to a number.
toSingleNum [1, 3, 4]
read $ concat $ map show [1, 3, 4]
read $ concat $ ["1", "3", "4"]
read $ "134"
134
Further Reading:
If you're interested in Haskell, I'd recommend Graham Hutton's excellent "Programming in Haskell", or one of the tutorials listed on the Haskell Wiki.
First, split the list into chunks:
chunk n = unfoldr split
where
split [] = Nothing -- stop
split xs = Just $ splitAt n xs -- keep going
ghci> chunk 3 [1..6]
[[1,2,3],[4,5,6]]
The chunk function continues chopping n-sized chunks off the input list, until the list is empty. (unfoldr is one of the most under-appreciated functions in the standard library, by the way.)
Then turn each chunk into a number:
cumulate = foldl' (\x y -> x * 10 + y) 0
ghci> cumulate [4,5,6]
456
Now, compose these two functions together:
coalesce = map cumulate . chunk
ghci> coalesce [5,5,5,6,6,6]
[555,666]