继续传球风格vs monads

时间:2010-12-24 10:58:48

标签: functional-programming monads continuation-passing

延续传递样式(cps)和monad之间有什么区别。

4 个答案:

答案 0 :(得分:23)

The essence of functional programming中所述:

  

使用monad编程强烈让人想起延续传递风格(CPS),本文探讨了两者之间的关系。从某种意义上说,它们是等价的:CPS作为monad的特例出现,任何monad都可以通过改变答案类型嵌入到CPS中。但是monadic方法提供了额外的洞察力,并允许更精细的控制。

那篇论文非常严谨,实际上并没有完全扩展CPS和monad之间的关系。在这里,我试图给出一个非正式的,但是说明性的例子:

(注意:以下是新手(我自己)对Monad的理解,虽然在写完之后看起来看起来像是那些高代表用户的答案之一。请大量拿盐)< / p>

考虑经典的Maybe monad

-- I don't use the do notation to make it 
-- look similar to foo below

bar :: Maybe Int
bar =
    Just 5 >>= \x ->
    Just 4 >>= \y ->
    return $ x + y

bar' :: Maybe Int
bar' =
    Just 5 >>= \x ->
    Nothing >>= \_ ->
    return $ x

GHCi> bar
Just 9
GHCi> bar'
Nothing

一旦遇到Nothing,计算就会停止,这里没什么新东西。让我们尝试使用CPS模仿这种monadic行为:

这是我们使用CPS的vanilla add函数。我们在这里使用所有Int而不是algebric数据类型来简化:

add :: Int -> Int -> (Int -> Int) -> Int
add x y k = k (x+y)

GHCi> add 3 4 id
7

注意它与monad的相似程度

foo :: Int
foo =
    add 1 2 $ \x -> -- 3
    add x 4 $ \y -> -- 7
    add y 5 $ \z -> -- 12
    z

GHCi> foo
12

行。假设我们希望计算的上限为10.也就是说,当下一步导致值大于10时,任何计算必须停止。这有点像说“一个可能计算必须停止并返回{{1} }只要链中的任何值都是Nothing)。让我们看看如何通过编写“CPS变换器”来实现它

Nothing

请注意,最终返回值可以是cap10 :: (Int -> Int) -> (Int -> Int) cap10 k = \x -> if x <= 10 then let x' = k x in if x' <= 10 then x' else x else x foo' :: Int foo' = add 1 2 $ cap10 $ \x -> -- 3 add x 4 $ cap10 $ \y -> -- 7 add y 5 $ cap10 $ \z -> -- 12 undefined GHCi> foo' 7 ,但这很好,因为评估在第3步(undefined)停止。

我们可以看到z用一些额外的逻辑包装“正常的延续”。这与monad非常接近 - 将计算与一些额外的逻辑相结合。

让我们更进一步:

cap10

吁!也许我们刚刚发明了(>>==) :: ((Int -> Int) -> Int) -> (Int -> Int) -> Int m >>== k = m $ cap10 k foo'' :: Int foo'' = add 1 2 >>== \x -> -- 3 add x 4 >>== \y -> -- 7 add y 5 >>== \z -> -- 12 undefined GCHi> foo'' 7 monad!

现在,如果我们查看source code of Cont,我们会看到Cap10

Cont

newtype Cont r a = Cont { runCont :: (a -> r) -> r } 的类型是

runCont

Cont r a -> (a -> r) -> r ((a -> r) -> r) -> (a -> r) -> r

的类型完全吻合

现在实际回答问题

现在输入所有内容后,我重新阅读原始问题。 OP要求“差异”:P

我猜不同之处在于CPS为调用者提供了更多控制权,而monad中的>>==通常由monad的作者完全控制。

答案 1 :(得分:7)

答案 2 :(得分:4)

Peyton Jones和Wadler撰写的一篇探讨该问题的有趣论文是"Imperative functional programming"

这是介绍monadic IO的论文,它与其他方法(包括CPS)进行了比较。

作者总结道:

  

所以monad比continuation更强大,但只是因为类型!目前尚不清楚这是否只是欣德利 - 米尔纳式系统的一个人工制品,或者这些类型是否揭示了基本重要性的差异(我们自己的直觉是后者 - 但它只是一种直觉。)

答案 3 :(得分:-10)

没有任何关系,因此问题与询问蓝色和冥王星之间的区别同样有意义。