Механика дай! в выражениях вычислений
В настоящее время я работаю над серией выражений для вычислений на потрясающем веб-сайте fsharpforfunandprofit, и у меня возник вопрос относительно урока 4 "Обернутый тип" серии вычислений. Я попытался прочитать немного дальше, но есть важное понятие, которое я не понимаю.
На самом деле, я понимаю определение связывания:
member Bind : M<'T> * ('T -> M<'U>) -> M<'U>
но одна вещь, которую я не понимаю на данный момент, это магия при использовании его в выражении вычисления с помощью let!:
Например, в:
let product'' =
dbresult {
let! custId = getCustomerId "Alice"
let! orderId = getLastOrderForCustomer "" // error!
let! productId = getLastProductForOrder orderId
printfn "Product is %s" productId
return productId
}
printfn "%A" product''
getCustomerId "Алиса" возвращает мне M<'T>, но custId - это уже развернутый' T, и я нигде не вижу, как работает этот фокус...
Является ли это частью кода, скрытого в let! Инструкция в сборке ядра Fsharp? Может ли кто-нибудь объяснить мне, как пусть! достать Т 'из своей обертки?
Спасибо за ваши объяснения
1 ответ
Этот:
let product'' =
dbresult {
let! custId = getCustomerId "Alice"
let! orderId = getLastOrderForCustomer "" // error!
let! productId = getLastProductForOrder orderId
printfn "Product is %s" productId
return productId
}
будет desugar к чему-то вроде (назвав тип монады просто DB<'t>
):
let product'' =
DB.Delay(fun () ->
DB.Bind(getCustomerId "Alice",(fun custId ->
DB.Bind(getLastOrderForCustomer "",(fun orderId ->
DB.Bind(getLastProductForOrder orderId, (fun productId ->
printfn "Product is %s" productId
DB.Return productId)))))))
так что в основном вы получаете Bind
уровень для каждого let!
(обычно вы можете игнорировать Delay
)
Как вы можете видеть, синтаксис вычислительных выражений намного лучше, чем вложенный Binds
- большинство языков, которые поддерживают монадические выражения некоторого вида, имеют похожий синтаксический сахар - даже C# (from ... in ... select
он же LINQ)