【问题标题】:What good is the monad instance of Cont?Cont 的 monad 实例有什么用?
【发布时间】:2014-06-10 18:02:50
【问题描述】:

我在玩 CPS 和 Control.Monad.Cont,想知道我们通过注意到单子结构获得了什么。对于这样的代码:

sumOfSquares'cps :: Cont r Int -> Cont r Int -> Cont r Int
sumOfSquares'cps x y = x >>= \x' ->
                       y >>= \y' ->
                       return (x'*x' + y'*y')

可以很容易地改写为

type Cont' r a = (a -> r) -> r

sos'cps :: Cont' r Int -> Cont' r Int -> Cont' r Int
sos'cps x y = \k -> x $ \x' -> 
                    y $ \y' -> 
                    k (x'*x' + y'*y') 

不要误会我的意思,但除了能够使用do 符号和newtype 之外,我看不到这里的感觉。我也不认为 callCC 依赖于 monad 实例。

我缺乏想象力来举一个例子。声明 Cont r 一个 monad 我们实际上得到了什么?

【问题讨论】:

  • “我认为callCC 也不依赖于 monad 实例”。严格来说,什么都不是。例如,在 Maybe monad return = Just(=<<) = maybe Nothing 中。 Monad 类对预先存在的功能进行了抽象,以使 Michael Snoyman 在他的回答中提到的事情成为可能。
  • 有道理,仔细想想。虽然通常当我看到使用 bind 重构的函数时,我的胃里会有一种舒适温暖的感觉,告诉我我做对了。我不明白Cont,因为我猜在语法上没有真正的区别。
  • 要了解为什么Cont 的语法糖看起来特别薄,您可能需要查看The Mother of all Monads

标签: haskell monads continuation-passing


【解决方案1】:

您可以向 any Monad 提出相同的问题。在我的脑海中,我能想到三个优点:

  1. 您可以访问大量旨在与Monads 配合使用的函数。
  2. 您可以使用do-notation。
  3. 您可以堆叠 monad 转换器来创建更强大的东西。

这还可以让您更好地推理代码,因为您可以依赖身份和关联属性等。

【讨论】:

  • 这些是发布问题后立即出现在我脑海中的事情:)。我想我对几乎相同的语法感到失望,另一个 monad 中的绑定运算符使代码变得整洁。这很幼稚,因为 monad 的目的与增强语法不同。
【解决方案2】:

一个明显的优势是您可以使用为Monads(和Functors)定义的组合子。例如,您的函数可以使用liftM2 编写:

sumOfSquares'cps :: Cont r Int -> Cont r Int -> Cont r Int
sumOfSquares'cps = liftM2 sumSquares
  where sumSquares x y = x * x + y * y

此函数不依赖于 Cont 的 monad,并且可以使用更通用的类型来编写,例如

sumOfSquaresM :: Monad m => m Int -> m Int -> m Int

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-20
    • 2017-03-25
    • 1970-01-01
    • 2016-01-18
    • 2014-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多