繁体   English   中英

如何将F#stm编写为>> =管道

[英]How to write F# stm as >>= pipeline

有人可以解释一下如何将此FSharpx 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的>> =管道。

谢谢!

更新:为了避免混淆,需要进行一些澄清:

我在想,应该能够根据stm.Bind和stm.Return在F#中定义>> =运算符。 我迷路了,试图自己做。

UPDATE2:在Thomas回答之后,我发布了更新版本,我认为它看起来还不错。 如果我理解正确,由于缺少类型类,运算符>> =的功能与Haskell不同。

我同意这对于F#来说不是惯用的,但这可能是一个很好的练习。

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

谢谢!

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#中monad的一种好方法(特别是如果您来自Haskell背景),但这不是惯用方式-F#中的惯用方式是显式使用计算。

这种方法的一个局限性(与Haskell相比)是>>=在单子组上不是多态的,因此您没有获得任何收益。 另外,我认为人们普遍认为使用计算块更具可读性(对于F#开发人员)

在Haskell中使用atomically将STM表达式转换为IO的主要区别是,将单子结果(也就是计算表达式)绑定到名称(使用<-运算符)的语法不同,并且默认情况下Haskell列表是惰性的,这意味着您不需要使用Seq库(据我所知,它在F#中为您提供了惰性列表)。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM