gpt4 book ai didi

haskell - 如何提取定界延续(重置/移位)以供将来在 Haskell 中使用?

转载 作者:行者123 更新时间:2023-12-05 02:27:55 25 4
gpt4 key购买 nike

以下是使用定界延续(重置/移位)的简单示例:

import Control.Monad
import Control.Monad.Trans
import Control.Monad.Trans.Cont

test :: Integer
test = evalCont . reset $ do
r <- shift $ \k -> do
return $ k 10
return $ 1 + r

λ> test1
11

效果不错。

但是,我想将延续 k 提取为纯函数以供将来使用,而不是仅仅在 shift 中调用它。

比如我希望test2可以返回k:

test2 :: Integer -> Integer
test2 = evalCont . reset $ do
r <- shift $ \k -> do
return $ k
return $ 1 + r

但是 GHC 提示:

    ? Couldn't match type 'Integer -> Integer' with 'Integer'
Expected type: Cont (Integer -> Integer) (Integer -> Integer)
Actual type: ContT
(Integer -> Integer)
Data.Functor.Identity.Identity
((Integer -> Integer) -> Integer -> Integer)
? In a stmt of a 'do' block: return $ k
In the expression: do return $ k
In the second argument of '($)', namely '\ k -> do return $ k'
|
88 | return $ k
| ^^^^^^^^^^

谁能帮我解决这个问题?

谢谢。

最佳答案

标准的 Cont 是不完全通用的。 “真实”Cont 看起来像这样

newtype Cont    i o a =    Cont { runCont :: (a -> i) -> o }
-- versus the standard
newtype SadCont r a = SadCont { sadCont :: (a -> r) -> r }
-- SadCont r a = Cont r r a

使用标准的 SadCont 是因为它支持 >>=return 它们通常的类型(所以它可以是一个 单子(monad)).但是 Cont 中的“真正的”分隔延续允许每个 shift 从延续中获取一种类型的值并将它们发送到前一个 shift/重置 为不同的类型。在这种情况下,您只是将 整个 延续作为从 shiftreset 的函数传递。

{-# LANGUAGE RebindableSyntax #-}
-- ^ placing this at the top of a file or passing -XRebindableSyntax to GHC allows do notation to use custom (>>=) and (>>)

-- not Monad operations!
return :: a -> Cont r r a
return x = Cont ($ x)
(>>=) :: Cont m o a -> (a -> Cont i m b) -> Cont i o b
Cont x >>= f = Cont $ \k -> x (($ k) . runCont . f)
(>>) :: Cont m o a -> Cont i m b -> Cont i o b -- RebindableSyntax also wants this
a >> b = a >>= const b

evalCont :: Cont a o a -> o
evalCont (Cont x) = x id

-- shift/reset are actually just
reset = evalCont
shift = Cont
-- note that the types of reset and shift differ significantly from transformers
-- reset returns a pure value here and shift requires a pure value from its function
-- I think my choices are more correct/standard, e.g. they line up with the old Scala shift/reset http://lampwww.epfl.ch/~hmiller/scaladoc/library/scala/util/continuations/package.html

在你的例子中

test2 :: Integer -> Integer
test2 = reset $ do
r <- shift $ \k -> k
return $ 1 + r

TL;DR Cont 被故意“破坏”,因此它失去了不同输入和输出类型的通用性,但获得了 Monadicity。您可以通过将输入和输出类型放入您发现的(递归)总和来破解它。或者(这个答案)你可以定义和使用“真实的”Cont

关于haskell - 如何提取定界延续(重置/移位)以供将来在 Haskell 中使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72833519/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com