For a while F# has supported the ability to auto-quote using [<ReflectedDefinitionAttribute>]
. Is there anything similar for laziness?
e.g.
member __.Quoted ([<ReflectedDefinitionAttribute>] quotation:Expr<'T>) = ...
member __.Thunked ([<LazyAttribute>] thunk:Lazy<'T>) = ...
I suppose I could use something like
member __.Quoted ([<ReflectedDefinitionAttribute>] quotation:Expr<'T>) =
Lazy (evaluate (<@ fun () -> %quotation @>)) // evaluate using Unquote or similar
But wouldn't this be costly?
UPDATE:
I found a hack, it's not exactly what I would like but it give the correct behavior.
type Signal = Signal with
member __.Return x = x
member __.Delay (f:unit -> _) = f
let a = Signal { return randint }
let b = Signal { return randint }
let c = Signal { return a() + b() }
There is nothing like the
ReflectedDefinition
attribute for automatically turning things into delayedLazy<'T>
computations.You are right that automatically quoting the argument achieves something like this. You could use the (very limited)
LeafExpressionConverter.EvaluateQuotation
to do this for some limited kinds of expressions, but as you note, this would be inefficient. The following is a proof of concept though (but you cannot call custom functions in the branches as this uses LINQ expressions):In practice, I think a more reasonable approach is to just use the built-in
Lazy<'T>
values. F# has a (not widely known)lazy
keyword that gives you a bit nicer syntax for creating those: