I found this expression while studying functional reactive programming, from "Fixing a Space Leak with an Arrow" by Hai Liu and Paul Hoodak (page 5):
Suppose we wish to define a function that repeats its argument indefinitely: repeat x = x : repeat x or, in lambdas: repeat = λx → x : repeat x This requires O(n) space. But we can achieve O(1) space by writing instead: repeat = λx → let xs = x : xs in xs
The difference here seems small, but it extremely suggests the effectiveness of space. Why and how is this happening? The best guess I made was to evaluate them manually:
r = \x -> x: rx r 3 -> 3: r 3 -> 3: 3: 3: ........ -> [3,3,3,......]
As above, we will need to create endless new thunks for this recursion. Then I try to evaluate the second:
r = \x -> let xs = x:xs in xs r 3 -> let xs = 3:xs in xs -> xs, according to the definition above: -> 3:xs, where xs = 3:xs -> 3:xs:xs, where xs = 3:xs
In the second form, xs appears and can be divided between all the places it encounters, so I assume that we can use only the spaces O(1) , not O(n) . But I'm not sure if I'm right or not.
BTW: the keyword "shared" comes from the same page 4:
The problem is that standard on-demand evaluation rules cannot recognize that a function:
f = λdt → integralC (1 + dt) (f dt)
matches with:
f = λdt → let x = integralC (1 + dt) x in x
The previous definition makes the job repeat in a recursive call to f, whereas in the latter case, the calculation is general.
haskell frp
snowmantw May 19 '13 at 6:48 a.m. 2013-05-19 06:48
source share