2014-01-13 4 views
0

Может кто-нибудь объяснить, как написать этот FSharpx stm в качестве конвейера?Как написать F # stm как >> = конвейер

stm { 
     let! allTops = readTVar tAllTops 
     let! thisPlayerTops = mapM removeOtherPlayersScores allTops 
     let! markedTops = mapM markAsNonEmpty thisPlayerTops 

     return 
      markedTops 
      |> Seq.filter fst 
      |> Seq.map snd 
      |> List.ofSeq 
    } 

Я думаю о haskell-like >> = трубопроводах.

Спасибо!

UPDATE: Немного разъяснений для того, чтобы избежать путаницы:

Я думал, что один должен быть в состоянии определить >> = оператор в F # в терминах stm.Bind и stm.Return , Я попытался сделать это сам, я заблудился.

UPDATE2: После ответа Томаса я публикую обновленную версию, которая, я думаю, выглядит довольно хорошо. Если я правильно понимаю, из-за отсутствия типов классов оператор >> = не имеет такой же мощности, как в Haskell.

Я согласен, что это не идиоматично для F #, но это, вероятно, хорошее упражнение.

readTVar tAllTops 
    >>= mapM removeOtherPlayersScores 
    >>= mapM markAsNonEmpty 
    >>= stm.Return >> Seq.filter fst >> Seq.map snd >> List.ofSeq 
    |> atomically 

Спасибо!

ответ

1

>>= оператор в Haskell просто символическое имя связывают операции, так что вы можете определить его в F # просто как псевдоним для stm.Bind:

let (>>=) v f = stm.Bind(v, f) 

Использование оператора, вы может переписать код следующим образом:

readTVar tAllTops >>= fun allTops -> 
removeOtherPlayersScores allTops >>= fun thisPlayerTops -> 
mapM markAsNonEmpty thisPlayerTops >>= fun markedTops -> 
    markedTops 
    |> Seq.filter fst 
    |> Seq.map snd 
    |> List.ofSeq 
    |> stm.Return 

Это, безусловно, интересная вещь и хороший способ узнать о монадах в F # (особенно если вы исходите из фона Haskell), но это не идиоматический стиль - идиоматический стиль в F # заключается в том, чтобы явно использовать вычисления.

Одно ограничение этого подхода (по сравнению с Haskell) заключается в том, что >>= не является полиморфным над монадами, поэтому вы ничего не набираете. Кроме того, я думаю, что существует общее мнение о том, что использование блоков вычислений более читаемо (для разработчиков F #)

+0

Я не был уверен, как я должен был читать stm.Bind типа. Я добавил обновленное решение на основе вашего оператора >> = Спасибо! – vidi

0

Основное отличие, что выражение STM преобразуется в IO с помощью atomically в Haskell, разница синтаксис для связывания монадических результатов (аки вычисления выражений) к именам (с помощью оператора <-) и списков Haskell ленив по умолчанию, которые означает, что вам не нужно использовать библиотеку Seq (которая, насколько мне известно, дает вам ленивые списки в F #).

atomically $ do 
    allTops <- readTVar tAllTops 
    thisPlayerTops <- mapM removeOtherPlayersScores allTops 
    markedTops <- mapM markAsNonEmpty thisPlayerTops 
    return (map snd . filter fst $ markedTops) 
+0

Я понимаю, что это эквивалентный код haskell, но то, что я хотел бы иметь, это код F #, эквивалентный моей исходной stm , Я думал, что нужно определить оператор >> = в F # в терминах stm.Bind и stm.Return. Я попытался сделать это сам, я заблудился. – vidi

+0

О, извините, я полностью неверно истолковал вопрос! –

+0

... и, конечно же, спасибо за усилия ответить – vidi