It just occured to me how to use Computational Expressions to write a Generator/sequence expression for Lazy Lists.
Basically it is the list monad switching the list for the lazyList type.
#light
module LazyListMonad =
let result v = LazyList.cons v (LazyList.empty())
let bind (llist:'a LazyList) f = LazyList.map f llist |> LazyList.concat
let zero<'a> = LazyList.empty(): 'a LazyList
let append xs ys = LazyList.append xs ys
type LazyBuilder() =
member b.Bind (llist, f) = bind llist f
member b.Return (v) = result v
member b.Let (v, f) = bind (result v) f
member b.For (s, f) = bind (LazyList.of_seq s) f
member b.Combine (listA, listB) = LazyList.append listA listB
member b.Zero () = LazyList.empty ()
member b.Delay (f) = f():'a LazyList
let LazyL = new LazyListMonad.LazyBuilder()
let list =
LazyL
{ for i in 1 .. 6 do
for j in 10 .. 20 do
if i%2=0 && j%2=0 then
yield (i,j)
}
Not sure if the computational expression is implemented correctly but I just hacked that out in a few minutes after I had my eureka moment. Now what has me perplexed is the fact that using yield gets the following warning in fsi
warning FS0191: We recommend you use 'return' instead of '->' within computation expressions, as future extensions to the syntax may require this change.
are you guys planning to remove yield. I can swap it with return and it works fine. The only problem I have is using yield reads better.
Other than that the only thing left is to use a computation expression to describe a LazyList via its unfold function, and potentially combine both to have a robust computational expression that lets you describe a lazylist