Reputation: 25927
Having the following function:
between :: a -> [a] -> [[a]]
between i [] = [[i]]
between i r@(x:xs) = [[i]++r] ++ map f (between i xs)
where f = (\n->[x] ++ n)
And the result of between 0 [1,2]
being:
[[0,1,2],[1,0,2],[1,2,0]]
How is this possible? I am able to understand the two first cases:
[0,1,2]
because of [[0]++[1,2]]
[1,0,2]
because map f [[0]++[2]]
(where x is 1)Is the map recursing as well? And keeping a reference to all initial x
so it then just contacts all? In my head the final result would be something like:
[[0,1,2],[1,0,2],[2,0]]
PS: With "map recursing" as well is something a long the lines:
\n -> [1] + n
\n ->[2] + n
\n ->[3] + n
\n ->[m] + n
Upvotes: 2
Views: 87
Reputation: 54078
First of all, let's fix this function to use cons (:
) rather than ++
, since the former is more efficient and idiomatic when prepending an element to the front of a list, and it can also simplify the function a fair amount:
between i [] = [[i]]
between i r@(x:xs) = (i : r) : map (x:) (between i xs)
This will be easier to use to walk through the steps:
between 0 [1, 2] =
(0 : [1, 2]) : map (1:) (between 0 [2])
[0, 1, 2] : map (1:) ((0 : [2]) : map (2:) (between 0 []))
[0, 1, 2] : map (1:) ([0, 2] : map (2:) [[0]])
[0, 1, 2] : map (1:) ([0, 2] : [[2, 0]])
[0, 1, 2] : map (1:) [[0, 2], [2, 0]]
[0, 1, 2] : [1:[0, 2], 1:[2, 0]]
[0, 1, 2] : [[1, 0, 2], [1, 2, 0]]
[[0, 1, 2], [1, 0, 2], [1, 2, 0]]
So by equational reasoning, we can work out the steps GHC took to arrive at this answer.
Upvotes: 2
Reputation: 12070
But remember, between returns the result for the whole tail
between 0 [2]
gives
[[0, 2], [2, 0]]
applying f
prepends 1
to everything
[[1, 0, 2], [1, 2, 0]]
Finally, we add the [[i]++r]
(which would be better written as [i:r]
)
[[0, 1, 2], [1, 0, 2], [1, 2, 0]]
Upvotes: 1