【问题标题】:Is it an example of a Monad? If not, why?它是 Monad 的一个例子吗?如果不是,为什么?
【发布时间】:2018-12-05 06:36:11
【问题描述】:

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

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

typealias Rule = ([Card]) -> Result

其中 Result 是一种保存当前评估状态的类型(已经评估过排名的卡片、剩余的卡片、最后一个规则评估是否成功以及评估的排名)。输入是要评估的数组(可能是一组)卡片。

我也创建了这个函数:

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

从卡组中创建一个最小结果。

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 是单子吗?否则,为什么不呢?我的两个担忧是上面提到的。

我认为在这个具体示例中理解这些点(或知道这是一些其他盲点)将对我来说一点点单子概念。

谢谢!

【问题讨论】:

  • Monads 是围绕类型 constructors 构建的,而不是类型。例如,在 Haskell 中,[Int] 不是 monad,但 [] 是,因为您可以定义 return :: a -> [a](>>=) :: [a] -> (a -> [b]) -> [b]。所以严格来说,Result 可能不是单子。
  • Result 除了应用规则的布尔结果之外还实现了什么?请注意,您的 fullHouse 规则并未说明它将如何处理三类和一对不能重叠的要求。
  • 谢谢!它保留了两个额外信息:尚未评估的卡片子集(例如:三类规则的剩余两张卡片,帽子可能或不可能是对子)和找到的等级(例如:三同类,一张更高的牌和另一张可以用来比较手牌的牌)。还有一个布尔值来链接规则...
  • 好的,那么我想像type Result v = State HandInfo vandThen :: Rule -> Bool -> ResultBool 这样的东西,所以fullHouse h = threeOfAKind h >>= andThen pairevaluate h = royalFlush >>= otherwise straightFlush >>= ... >>= otherwise pair >>= otherwise highCardandThenotherWise 等。与其绑定函数不如工厂创建与>>= 绑定的函数。
  • 我想我没有得到最后一个,chepner...

标签: swift haskell functional-programming monads


【解决方案1】:

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 是一个 monad,但你不能实例化 List。但是,您可以实例化 List[Int]

如果您想从概念上了解如何使 monad 成为 monad,请观看 Brian Beckman 的视频 Don't Fear the Monad。此外,还有一系列不错的博文,Monads are Elephants

【讨论】:

    猜你喜欢
    • 2012-10-18
    • 2020-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-18
    • 1970-01-01
    • 1970-01-01
    • 2012-08-26
    相关资源
    最近更新 更多