1

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!!

Will Ness
  • 70,110
  • 9
  • 98
  • 181
klabe
  • 455
  • 1
  • 5
  • 13
  • 1
    Exactly which part are you stuck on? Do you understand most of it except for the actual `ruler` definition, or do you need help with understanding the various other `streamXXX` functions as well? – bradrn Mar 25 '19 at 03:37
  • Upvoted for being honest on the homework. No, ruler will not result in `0,1,0,1,...` since in such case `streamMap (+1) ruler` would be `1,2,1,2,...` and interleaving that with `0,0,0,...` does not result in `0,1,0,1,...`. It's more tricky. `0,1` looks the correct start, though. Try pretending that `ruler=0,1,x2,x3,x4,x5,...` for some unknowns `xi`, and try to infer what `x2` should be. Then, knowing `x2`, compute `x3`. And so on. You'll notice a pattern. – chi Mar 25 '19 at 12:48

2 Answers2

2

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 xs):

0 x 0 x 0 x 0 x 0 x 0 x ...

Now we'll start filling in those xs. 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.

bradrn
  • 8,337
  • 2
  • 22
  • 51
1

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:                                     
Will Ness
  • 70,110
  • 9
  • 98
  • 181