作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
以下是使用定界延续(重置/移位)的简单示例:
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
/重置
为不同的类型。在这种情况下,您只是将 整个 延续作为从 shift
到 reset
的函数传递。
{-# 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
被故意“破坏”,因此它失去了不同输入和输出类型的通用性,但获得了 Monad
icity。您可以通过将输入和输出类型放入您发现的(递归)总和来破解它。或者(这个答案)你可以定义和使用“真实的”Cont
。
关于haskell - 如何提取定界延续(重置/移位)以供将来在 Haskell 中使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72833519/
数据的可重现代码: import pandas as pd dict = {"a": "[1,2,3,4]", "b": "[1,2,3,4]"} dict = pd.DataFrame(list(d
我是一名优秀的程序员,十分优秀!