You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell中如何提取reset/shift分隔续延为纯函数供后续使用?

提取分隔续延为独立纯函数的实现方法

问题背景

以下是基于reset/shift实现的分隔续延基础可运行示例:

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

在GHCI中执行test将返回11,逻辑运行正常。

需求是不局限于在shift作用域内调用捕获的续延k,而是将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
   |         ^^^^^^^^^^

错误原因

类型不匹配的核心原因有两个:

  • shift捕获的续延k不是纯函数,类型为a -> Cont r b:接收输入后返回的是续延计算结构,而非直接输出纯值。
  • 直接返回k时,k的返回类型与reset块要求的最终结果类型r形成递归类型约束,GHC无法自动完成类型对齐。

实现方案

方案1:手动包装shift捕获的续延

在shift块内拿到k后,手动将其转换为纯函数:对任意输入x,嵌套一层reset限定k x的执行边界,再通过evalCont运行计算拿到纯结果,包装后的函数即可脱离shift作用域独立调用。

test2 :: Integer -> Integer
test2 = evalCont . reset $ do
    r <- shift $ \k -> do
        -- 将monadic续延转换为纯函数
        return $ \x -> evalCont . reset $ k x
    return $ 1 + r

运行验证:

λ> test2 10
11
λ> test2 20
21

完全符合预期,提取出的续延等价于\r -> 1 + r。

方案2:使用control操作符替代shift

Control.Monad.Trans.Cont提供的control操作符对应Felleisen的F控制算子,它捕获的续延不会自动绑定reset边界,直接返回的k就是可独立使用的纯函数,代码更简洁:

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

运行效果和方案1完全一致。


内容的提问来源于stack exchange,提问作者chansey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 02:30:54