문제

Can somebody please explain how to write this FSharpx stm as a pipeline?

    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
    } 

I'm thinking of haskell-like >>= pipelines.

Thanks!

UPDATE: A little bit of clarification in order to avoid the confusion:

I was thinking that one should be able to define the >>= operator in F# in terms of stm.Bind and stm.Return. I tried to do that myself by I got lost.

UPDATE2: After Thomas' answer I post the updated version which I think it looks pretty OK. If I understand correctly, because of lack of type-classes the operator >>= doesn't have the same power as in Haskell.

I agree that it's not idiomatic for F# but it's probably a good exercise.

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

Thanks!

도움이 되었습니까?

해결책

The >>= operator in Haskell is just a symbolic name for the bind operation, so you can define it in F# just as an alias for stm.Bind:

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

Using the operator, you could rewrite the code as follows:

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

This is certainly an interesting thing and a good way to learn about monads in F# (especially if you are coming from the Haskell background), but it is not an idiomatic style - the idiomatic style in F# is to use the computations explicitly.

One limitation of this approach (compared to Haskell) is that >>= is not polymorphic over monads, so you're not gaining anything. Also, I think that there is a general consensus that using the computation blocks is more readable (for F# developers)

다른 팁

The main difference that an STM expression is converted to IO using atomically in Haskell, the difference syntax for binding monadic results (aka computation expressions) to names (using the <- operator) and that Haskell lists are lazy by default, which means that you don't need to use the Seq library (which, as far as I know, gives you lazy lists in F#).

atomically $ do
  allTops <- readTVar tAllTops
  thisPlayerTops <- mapM removeOtherPlayersScores allTops
  markedTops <- mapM markAsNonEmpty thisPlayerTops
  return (map snd . filter fst $ markedTops)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top