механика пусть! в вычислительных выражениях

В настоящее время я работаю над серией вычислительных выражений на потрясающем веб-сайте fsharpforfunandprofit, и у меня есть вопрос относительно урока 4 «обернутый тип» серии вычислений. Я попытался прочитать немного дальше, но есть одна важная вещь, которую я не понимаю.

На самом деле, я понимаю определение bind:

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 "Alice" возвращает мне M ‹'T>, но custId уже является развернутым' T и Я нигде не вижу, как работает этот волшебный трюк ...

Это часть кода, спрятанного в let! инструкция внутри сборок ядра Fsharp? Может ли кто-нибудь объяснить мне, как пусть! достать букву Т из обертки?

Спасибо за ваши объяснения


person Arthis    schedule 19.05.2015    source источник
comment
это именно то, для чего Bind используется (разворачивание): вы можете думать о let! custId = ... как о просто Bind (getCustomerId "Alice") (fun custId -> ... the next line(s)), поэтому каждый let! даст вам еще один уровень Bind   -  person Random Dev    schedule 19.05.2015
comment
let! сам по себе является синтаксическим сахаром, который нужно связывать десахаром - вы можете найти некоторые подробности в этом сообщение от Дона   -  person Random Dev    schedule 19.05.2015
comment
Хорошо понял! Большое спасибо...   -  person Arthis    schedule 19.05.2015
comment
хотите, чтобы я обернул это в ответ? ... один момент   -  person Random Dev    schedule 19.05.2015


Ответы (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 aka LINQ )

person Random Dev    schedule 19.05.2015
comment
Я забыл, что на самом деле делал метод привязки bind (m, f). При сопоставлении m он применяет f к a и, таким образом, разворачивает значение для будущего использования. Большое вам спасибо. - person Arthis; 19.05.2015