8

我正在玩 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我们实际上得到了什么?

4

2 回答 2

10

你可以问任何 Monad相同的问题。在我的脑海中,我能想到三个优点:

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

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

于 2014-06-10T18:24:09.947 回答
6

一个明显的优势是您可以使用为Monads(and 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

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

sumOfSquaresM :: Monad m => m Int -> m Int -> m Int
于 2014-06-10T18:33:40.880 回答