可以“继续"吗?后处理其继续的结果 [英] Can a "Cont r a" post-process the result of its continuation
问题描述
Cont r a
类型代表采用延续a->r
并产生类型r
的结果的函数.因此,延续和整个Cont r a
都产生相同 type r
的结果.
the Cont r a
type stands for a function which takes a continuation a->r
and produces a result of type r
. So both the continuation and the entire Cont r a
produce a result of the same type r
.
我的问题是:两个结果一定是相同的 value ,还是Cont r a
可以对延续的结果进行后处理并产生不同的值,尽管类型为
My question is: are the two results necessarily the same value, or can a Cont r a
post-process the result from the continuation and produce a different value, albeit of the same type r
?
我尝试使用(+1)
进行后期处理(请注意+ 1 --<--
):
I tried using (+1)
for post-processing (note the + 1 --<--
):
c1 :: Int -> Cont r Int
c1 x = let y = 2*x
in cont $ \k -> (k y) + 1 --<--
现在不进行类型检查,因为我的后处理函数(+1)
仅接受类型属于Num
类型类的参数.但是,我传递了延续(k y)
的结果,该延续是某种r
类型的,不能保证属于Num
类型类.
Now that doesn't typecheck, because my post-processing function (+1)
only accepts an argument whose type belongs to the Num
typeclass. However, I pass the result of the continuation (k y)
which is of some type r
that is not guaranteed to belong to the Num
typeclass.
无论我对(k y)
做什么,它都必须是r->r
类型的函数.可以对所有r
执行此操作的唯一功能是id
函数,并且将id
用于后处理根本不是后处理.
Whatever I do to (k y)
, it must be a function of type r->r
. The only function which can do this for all r
is the id
function and using id
for post-processing is no post-processing at all.
但是,如果我将r
限制为Num
类型类,或者甚至将具体类型限制为Int
,则整个事情都会进行类型检查.然后产生预期的结果:
However, the whole thing does typecheck if I restrict r
to the Num
typeclass or even to the concrete type Int
. It then produces the expected result:
*Main> runCont (c1 1) id
3
我不太确定,
- 如果这样的后处理和限制
r
的类型是正常的事情,如果是的话,在什么情况下这可能有用 - 或者如果所有
r
的类型变量r
都必须读为,并且限制r
的类型将导致各种麻烦.
- if such post-processing and restricting the type of
r
is a normal thing to do, and if so, in what circumstances this might be useful - or if the type variable
r
has to be read as for allr
and restricting the type ofr
will lead to all sorts of trouble.
有人可以阐明这一点吗?
Can someone shed some light on this?
推荐答案
从技术上讲,我认为很好.从本质上讲,将Cont r a
专门化为Num r => Cont r a
似乎比将Reader r a
专门化为Num r => Reader r a
更为麻烦.
Technically, I think it's fine. Specializing Cont r a
to Num r => Cont r a
doesn't seem fundamentally more problematic than specializing Reader r a
to Num r => Reader r a
.
这样做的含义是,最终的CPS计算只能针对产生数字的(最终)连续进行,但这很明显-如果您有将连续结果作为数字进行后处理的计算,它只能与产生数字的延续一起使用!
An implication of doing so is that the resulting CPS computation can only be run against a (final) continuation that produces a number, but that's obvious -- if you have a computation that post-processes the continuation result as a number, it can only be used with continuations that produce numbers!
作为至少在某种程度上受到认可的其他证据,请注意有一个功能:
As additional evidence that this is sanctioned at least to some degree, note that there's a function:
mapCont :: (r -> r) -> Cont r a -> Cont r a
如果要不加限制地使用r
函数,则它的第一个参数的唯一有效值将是id
或不会终止的函数,如您所指出的那样.
If this function was to be used with no restriction on r
, the only valid values for its first argument would be id
or functions that don't terminate, as you have noted.
使用mapCont
的c1
版本可能如下:
c2 :: (Num r) => Int -> Cont r Int
c2 x = mapCont (+1) $ return (2*x)
似乎可以正常工作:
> runCont (c2 10) id
21
> runCont (c2 10) (const 5)
6
> runCont (c2 10) show
... No instance for (Num String) arising from a use of 'c2' ...
至于什么时候该有用 ,我不确定.我可以想到一些有些la脚的应用程序.您可以定义一个覆盖最终结果的计算(前提是不使用其他任何类型的后处理):
As for when this would be useful, I'm not sure. I can think of a few somewhat lame applications. You could define an computation that overrides the final result (provided no other kind of post-processing is used):
override x = cont (const x)
用法如下:
> runCont (return 2 >>= \x -> cont (\f -> f (x*3))) id
6
> runCont (return 2 >> override 1000 >>= \x -> cont (\f -> f (x*3))) id
1000
>
或模仿编写器以添加日志功能的计算转换器:
or a computation transformer that emulates a writer to add log functionality:
annotate note comp = mapCont (\(a, w) -> (a, note:w)) comp
您可能会这样使用:
runCont (annotate "two" (return 2)
>>= \x -> annotate "times three" (cont (\f -> f (x*3))))
(\a -> (a, []))
收益:
(6,["two","times three"])
但是,这些应用看起来并不十分引人注目.
These don't seem like very compelling applications, though.
这篇关于可以“继续"吗?后处理其继续的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!