2014-06-10 38 views
7

我玩弄CPS和Control.Monad.Cont,并想知道我们通过注意monadic结构获得什么。对于这样的代码:Cont的monad实例有什么好处?

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?

+3

“我不认为'callCC'依赖monad实例”。严格地说,从来没有。例如,在Maybe'monad'return = Just'和'(= <<)=也许Nothing'中。 Monad类抽象出先前存在的功能,以使Michael Snoyman在他的回答中提到的可能性。 – duplode

+0

有意思,思考一下。虽然通常当我看到使用绑定的重构函数时,我在我的胃里感受到一种温暖的温暖感觉,这告诉我我做了正确的事情。我不明白'Cont',因为在语法上我没有真正的区别。 –

+1

要理解为什么句法糖对于'Cont'看起来特别薄,你可能想查看[The Monads of Monads]​​(http://blog.sigfpe.com/2008/12/mother-of-all- monads.html)。 –

回答

9

你可能会问同样的问题任何Monad。关闭我的头顶,我能想到的三个优点:

  1. 您可以访问的,旨在与Monad s到工作职能的巨大集合。
  2. 您可以使用do -notation。
  3. 你可以叠加monad变压器来创建更强大的功能。

这也可以让你更好地理解你的代码,因为你可以依靠身份和关联属性等。

+1

这些都是发布问题后弹出到我脑海中的东西:)。我想我对另一个monad中绑定操作符使代码类型整齐的几乎相同的语法感到失望。这太天真了,因为monads服务的目的不同于增强语法。 –

6

一个明显的优点是,您可以使用为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并可以用更通用的类型例如写

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