Пропустить "сделать!"в вычислительном выражении - PullRequest
13 голосов
/ 03 января 2011

Можно ли собрать компоновщик выражений вычислений, который может упорядочить два или более выражений, не помещая перед ними do!?

Если я прочитал соответствующий раздел вРуководство правильно, это должно быть возможно с помощью метода Combine строителя.Однако мой Combine метод, похоже, не используется;вместо этого я получаю предупреждение компилятора, предлагающее использовать ignore для отбрасывания результата.

Например, учитывая монаду F # State , я бы хотел сделать это:

let hello who = State (fun lines -> lines @ [sprintf "hello %s" who])
let m = state {
    hello "world"
    hello "F#"
}
let l = Execute m []
// l should now contain ["hello world"; "hello F#"]

Ответы [ 2 ]

7 голосов
/ 03 января 2011

В дополнение к тому, что написал Дарио, вы не можете переопределить обычную последовательность, чтобы вести себя как монадическая do! (даже если вы решили не поддерживать немонадные операции в своих вычислениях).Проблема в том, что обычная последовательность не обрабатывается переводчиком каким-либо особым образом, поэтому нет точки перехвата, которую вы могли бы использовать.Ваш пример будет переведен так:

let m = state.Delay(fun () ->
  hello "world"
  hello "F#"
  state.Zero())

Вызов hello не включен ни в один вызов участника, который может быть переопределен.

В более ранней версии последовательности F # использовался для преобразования в вызовы Let члена, например:

let m = state.Delay(fun () ->
  state.Let(hello "world", fun _ ->
    state.Let(hello "F#", fun _ -> 
      state.Zero())))

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

5 голосов
/ 03 января 2011

Нет, потому что именно для этого и используется do. Если вы хотите сделать монадическое, то есть do!, вы должны быть явными. Пример:

let m = state {
    printfn "World"
    hello "World"
    return 42
}
  • Выражение printfn имеет тип unit, и существует неявное do printfn.
  • А в случае hello? Нам нужно монадическое связывание!

Теперь, как компилятор узнает, что выбрать, do или do!? Может быть, по типам (это делает Scala), но сейчас это не так. Так что это просто предполагает регулярное do в любом месте.

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