Я не думаю, что вам нужны ленивые значения - ленивое значение вычисляется один раз, когда это необходимо, но впоследствии его значение не изменяется.В вашем случае вам нужно Force
для переоценки значения в случае изменения некоторых зависимостей.Вы можете определить что-то вроде этого:
type Delayed<'T> =
| Delayed of (unit -> 'T)
member x.Force() = let (Delayed f) = x in f()
let delay f = Delayed f
Это представляет задержанное значение (на самом деле, просто функция) с помощью метода Force
, который будет оценивать его при каждом обращении к нему.Если вы переписываете код, используя delay
, он ведет себя так, как вы хотели:
let mutable add2 = fun x-> x+2
let mutable mult3 = fun x-> x*3
let mutable com = delay(fun () -> add2 >> mult3)
let mutable com2 = com
add2 <- fun x -> x
com.Force() 3 |> printfn "%A"
add2 <- fun x -> x + 4
com2.Force() 3 |> printfn "%A"
В отличие от lazy, это не делает никакого кэширования, поэтому двойной вызов Force
просто сделает все это дважды.Вы можете добавить некоторое кэширование, отслеживая граф зависимостей вычислений, но это усложняется.