Я использую F # v 1.9.6.2, и я определил очень простое выражение для вычисления:
type MaybeBuilder() =
member this.Let(x, f) =
printfn "this.Let: %A" x
this.Bind(Some x, f)
member this.Bind(x, f) =
printfn "this.Bind: %A" x
match x with
| Some(x) when x >= 0 && x <= 100 -> f(x)
| _ -> None
member this.Delay(f) = f()
member this.Return(x) = Some x
let maybe = MaybeBuilder()
Я набросал несколько операторов print в коде, чтобы сказать мне, какие методы вызываются в вычислительном выражении. Когда я выполняю следующее заявление:
maybe {
let x = 12
let! y = Some 11
let! z = Some 30
return x + y + z
}
Я ожидаю, что консоль распечатает следующее:
this.Let 12
this.Bind Some 12
this.Bind Some 11
this.Bind Some 30
Но мои реальные результаты таковы:
this.Bind: Some 11
this.Bind: Some 30
Другими словами, F # не выполняет член Let
. Когда я перезаписываю Let
, чтобы вызвать исключение, код запускается без исключения. Кроме того, когда я полностью закомментирую элемент Let
, я не получаю сообщение об ошибке, указывающее The field, constructor or member 'Let' is not defined
, и код выполняется должным образом.
(Я пытался исследовать код с помощью Reflector, но, как это обычно бывает, декомпилированный F # искажен за пределы читабельности.)
Похоже, спецификация для выражений вычислений изменилась. Привязки let
больше не рассматриваются как синтаксический сахар, и члены Let
больше не требуются в рабочих процессах вычислений?