它是Monad的一个例子吗?如果没有,为什么?

时间:2018-06-26 13:52:16

标签: swift haskell functional-programming monads

我正在尝试研究应用于Swift(一种多范式语言)的函数式编程。我向自己提出的一种练习是尝试做一个声明式的扑克手评估程序。

下面是一些代码摘录和我的问题:

typealias Rule = ([Card]) -> Result

“结果”是一种类型,用于保存当前评估状态(已在等级上评估过的牌,如果最后一次规则评估成功与否,则评估剩余牌数和评估等级)。输入是要评估的阵列(可以是一组)卡。

我还创建了此功能:

func id(_ hand:[Card]) -> Result ...

这将从卡片组中产生最少的结果。

结果还具有一组链接规则评估的功能(在此简化):

func apply(_ rule:Rule) -> Result
func andThen(_ rule:Rule) -> Result
func andAlso(_ rule:Rule) -> Result
func otherwise(_ rule:Rule) -> Result
func continueWith(_ rule:Rule) -> Result

什么使我可以将扑克排名规则声明为:

let fullHouse = { (hand) in
   threeOfAKind(hand).andThen(pair)
}

let royalStraightFlush = { (hand)  in
  straightFlush(hand).andAlso(straightAceHigh)
}

并将所有排名规则链接为:

let evaluate = { (hand) in
//id(hand)
    royalStraightFlush(hand)
    .otherwise(straightFlush)
    .otherwise(fourOfAKind)
    .otherwise(fullHouse)
    .otherwise(flush)
    .otherwise(straight)
    .otherwise(threeOfAKind)
    .otherwise(twoPair)
    .otherwise(pair)
    .continueWith(highCard) }

Result,原样:

  • 将类型([Card])包含到更广泛的上下文(R a)中
  • 具有id(结果)函数,该函数将类型为a的对象放入最小的“结果”上下文中(a-> R a)

但是...

  • 它不仅具有一个通用的>> =绑定函数,而且还具有多个特定的函数,它需要R a->(a-> R a)-> R a,它可以链接规则并将卡设置为从先前的部分结果状态进行评估。

  • (由于已实现)它的通用性不足以代替Card或[Card]处理其他类型。另一方面,我认为相同的链接逻辑可以在其他规则系统上进行一些更改...

我的问题是:Result是单子吗?否则,为什么不呢?我的两个关注是上面提到的那些。

我认为了解此具体示例上的这些要点(或知道这是其他一些盲点)将使我对monad概念有所了解。

谢谢!

1 个答案:

答案 0 :(得分:0)

Monad必须遵守三项Monad法律:

  • 左身份:return a >>= f ≡ f a
  • 正确的身份:m >>= return ≡ m
  • 关联性:(m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)

这还意味着为您的monad实现了return(或等效项)和>>=(通常称为bind,flatmap等)。Haskell(和其他语言)还添加了map函数(>>),即使可以根据>>=来实现。

此外,正如@chepner指出的那样,monad是本身并不是具体类型的抽象。它们是通用的,只能通过类型构造函数实例化。 List是单子,但是您无法实例化List。但是,您可以实例化List[Int]

如果您想对将单子变成单子的概念有一个很好的了解,请看Brian Beckman的视频Don't Fear the Monad。另外,还有一系列不错的博客文章Monads are Elephants

相关问题