Да, я думаю, что синтаксис F # для выражений вычислений уникален тем, что обеспечивает прямую синтаксическую поддержку для различных типов вычислений. Может использоваться для работы с моноидами , обычными монадами , а также MonadPlus вычислениями из Haskell.
Я написал об этом во введении моей магистерской диссертации . Я считаю, что это довольно читабельная часть, поэтому вы можете перейти на страницу 27, чтобы прочитать ее. В любом случае, я скопирую примеры здесь:
Моноид используется только для объединения значений с использованием некоторой операции "+" (Combine
). Вы можете использовать его, например, для построения строк (это неэффективно, но демонстрирует идею):
type StringMonoid() =
member x.Combine(s1, s2) = String.Concat(s1, s2)
member x.Zero() = ""
member x.Yield(s) = s
let str = new StringMonoid()
let hello = str { yield "Hello "
yield "world!" };;
Монады являются знакомым примером, в котором используются bind и return операций выражений вычислений. Например, возможно монада представляет вычисления, которые могут в любой момент завершиться с ошибкой:
type MaybeMonad() =
member x.Bind(m, f) =
match m with Some(v) -> f v | None -> None
member x.Return(v) = Some(v)
let maybe = new MaybeMonad()
let rec productNameByID() = maybe {
let! id = tryReadNumber()
let! prod = db.TryFindProduct(id)
return prod.Name }
Аддитивные монады (он же MonadPlus
в Хаскеле) представляет собой комбинацию из двух. Это немного похоже на монадическое вычисление, которое может давать несколько значений. Типичным примером является список (или последовательность ), который может реализовывать комбинации bind и :
type ListMonadPlus() =
member x.Zero() = []
member x.Yield(v) = [v]
member x.Combine(a, b) = a @ b
member x.Bind(l, f) = l |> List.map f |> List.concat
let list = new ListMonadPlus()
let cities = list {
yield "York"
yield "Orleans" }
let moreCities = list {
let! n = cities
yield n
yield "New " + n }
// Creates: [ "York"; "New York"; "Orleans"; "New Orleans" ]
Есть несколько дополнительных ключевых слов, которые не соответствуют напрямую какой-либо теоретической идее. Ключевое слово use
относится к ресурсам, а for
и while
могут использоваться для создания циклов. Понимание последовательности / списка фактически использует for
вместо let!
, потому что это имеет гораздо больше смысла с синтаксической точки зрения (и for
обычно принимает некоторую последовательность - хотя она может быть, например, асинхронной).