问题
I am doing the homework of CIS 194. The problem is to implement the ruler function by using streamInterleave
. The code looks like
data Stream a = Cons a (Stream a)
streamRepeat :: a -> Stream a
streamRepeat x = Cons x (streamRepeat x)
streamMap :: (a -> b) -> Stream a -> Stream b
streamMap f (Cons x xs) = Cons (f x) (streamMap f xs)
streamInterleave :: Stream a -> Stream a -> Stream a
streamInterleave (Cons x xs) ys = Cons x (streamInterleave ys xs)
ruler :: Stream Integer
ruler = streamInterleave (streamRepeat 0) (streamMap (+1) ruler)
I am really confused why ruler can be implemented like this. Is this going to give me [0,1,0,1....]
?
Any help will be greatly appreciated. Thank you!!
回答1:
Firstly, we'll represent a Stream
like this:
a1 a2 a3 a4 a5 ...
Now, let's take the definition of ruler
apart:
ruler :: Stream Integer
ruler = streamInterleave (streamRepeat 0) (streamMap (+1) ruler)
In Haskell, an important point is laziness; that is, stuff doesn't need to be evaluated until it needs to be. This is important here: it's what makes this infinitely recursive definition work. So how do we understand this? We'll start with the streamRepeat 0
bit:
0 0 0 0 0 0 0 0 0 ...
Then this is fed into a streamInterleave
, which interleave this the with (as yet unknown) stream from streamMap (+1) ruler
(represented with x
s):
0 x 0 x 0 x 0 x 0 x 0 x ...
Now we'll start filling in those x
s. We know already that every second element of ruler
is 0
, so every second element of streamMap (+1) ruler
must be 1
:
1 x 1 x 1 x 1 x 1 x ... <--- the elements of (streamMap (+1) ruler)
0 1 0 x 0 1 0 x 0 1 0 x 0 1 0 x 0 1 0 x ... <--- the elements of ruler
Now we know every second element out of each group of four (so numbers 2,6,10,14,18,...) is 1
, so the corresponding elements of streamMap (+1) ruler
must be 2
:
1 2 1 x 1 2 1 x 1 2 ... <--- the elements of (streamMap (+1) ruler)
0 1 0 2 0 1 0 x 0 1 0 2 0 1 0 x 0 1 0 2 ... <--- the elements of ruler
Now we know that every fourth element out of each group of eight (so numbers 4,12,20,...) is 2
so the corresponding elements of streamMap (+1) ruler
must be 3
:
1 2 1 3 1 2 1 x 1 2 ... <--- the elements of (streamMap (+1) ruler)
0 1 0 2 0 1 0 3 0 1 0 2 0 1 0 x 0 1 0 2 ... <--- the elements of ruler
And we can continue building ruler
like this ad infinitum, by substituting back each n/2, 3n/2, 5n/2, ...
numbered value of ruler
.
回答2:
In Haskell notation, with []
in place of Stream
(which is isomorphic to infinite lists),
ruler = interleave (repeat 0)
(map (+1) ruler)
[ruler !! i | i <- [0..]] == concat . transpose $
[ repeat 0
, map (+1) ruler]
Splitting the ruler
into two alternating sub-sequences to match, we get
[ruler !! 2*i | i <- [0..]] == repeat 0
== [0 | i <- [0..]] -- {0} --
[ruler !! 2*i+1 | i <- [0..]] == map (+1) ruler
== map (+1) $ concat . transpose $
[ [ruler !! 2*i | i <- [0..]]
, [ruler !! 2*i+1 | i <- [0..]]]
concat . transpose $ == concat . transpose $
[[ruler !! 2*i+1 | i <- [0,2..]] [ [1 | i <- [0..]]
,[ruler !! 2*i+1 | i <- [1,3..]]] , [1 + ruler !! 2*i+1 | i <- [0..]]]
Splitting again,
[ruler !! 4*i+1 | i <- [0..]] == [1 | i <- [0..]] -- {1} --
[ruler !! 4*i+3 | i <- [0..]] == concat . transpose $
[ [1 + ruler !! 2*i+1 | i <- [0,2..]]
, [1 + ruler !! 2*i+1 | i <- [1,3..]]]
and again,
[ruler !! 8*i+3 | i <- [0..]] == [2 | i <- [0..]] -- {2} --
[ruler !! 8*i+7 | i <- [0..]] == ....
You should be able to see it through from here:
.... 16*i+7 ..... 3 -- {3} --
.... 32*i+15 ..... 4 -- {4} --
.... 64*i+31 .....
....
Thus,
ruler !! 2^(k+1)*i + 2^k - 1 == k , k <- [0..] , i <- [0..]
0: i => 2i
1: 2i+1 => 4i+1
2: 4i+3 => 8i+3
3: 8i+7 => 16i+7
4: 16i+15 => ....
5:
来源:https://stackoverflow.com/questions/55330709/implementing-the-ruler-function-using-streaminterleave