Запустить метод в выражениях вычислений - PullRequest
3 голосов
/ 15 октября 2010

Каков статус метода Run() в методе вычислений? Я видел это в нескольких примерах ( здесь , здесь , здесь ), и я видел в нем исходный код компилятора F #, но его нет spec или MSDN документация . Я подал проблему в MS Connect по этому поводу, и она была закрыта как «намеренно» без дальнейших объяснений.

Так что это устарело / недокументировано / не поддерживается? Стоит ли этого избегать?

ОБНОВЛЕНИЕ : Состояние проблемы MS Connect было быстро изменено, и страница MSDN обновлена ​​и теперь включает в себя Run ()

Ответы [ 2 ]

8 голосов
/ 15 октября 2010

6.3.10 Вычислительные выражения

В частности, вычислительные выражения имеют вид builder-expr {cexpr}, где cexpr - синтаксически грамматика выражений с дополнительными конструкциями, определенными в comp-выраж.Вычислительные выражения используются для последовательностей и других нестандартных интерпретаций синтаксиса выражений F #.Выражение builder-expr {cexpr} переводит в

let b = builder-expr in b.Run (b.Delay(fun () -> {| cexpr |}C)) 

для новой переменной b.Если при проверке этого выражения не существует метода Run в предполагаемом типе b, этот вызов опускается.Аналогичным образом, если метод Delay не существует для> типа b, когда проверяется это выражение, этот вызов опускается

4 голосов
/ 15 октября 2010

Я думаю, что метод Run был добавлен довольно поздно в процессе разработки, так что это, вероятно, причина, почему он отсутствует в документации. Как объясняет desco, метод используется для «запуска» вычислительного выражения. Это означает, что всякий раз, когда вы пишете expr { ... }, переведенный код будет заключен в вызов к Run.

Метод немного проблематичен, потому что он нарушает композиционность. Например, разумно требовать, чтобы для любого выражения вычисления следующие два примера представляли одно и то же:

expr { let! a = foo()           expr { let! c = expr {  
       let! b = bar(a)                   let! a = foo()
       let! c = woo(b)                   let! b = bar(a) 
       return! zoo(c) }                  return! woo(b) }
                                       return! zoo(c) }

Однако метод Run будет вызываться только для общего результата в левом примере и два раза справа (для общего выражения вычисления и для вложенного выражения). Обычная сигнатура типа метода - M<T> -> T, что означает, что правильный код даже не скомпилируется.

По этой причине рекомендуется избегать этого при создании монад (как они обычно определяются и используются, например, в Haskell), потому что метод Run нарушает некоторые приятные аспекты монад. Однако, если вы знаете, что делаете, то это может быть полезно ...

Например, в моем коде break построитель вычислений немедленно выполняет свое тело (в объявлении), поэтому добавление Run для разворачивания результата не нарушает композиционность - составление означает просто запуск другого кода. Однако определение Run для async и других отложенных вычислений вообще не является хорошей идеей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...