![](/img/trans.png)
[英]Is it possible to write a function of signature `Monad m => m a -> forall r. m r` such that the original return value is preserved?
[英]How to understand that the types a and forall r. (a -> r) -> r are isomorphic
在Thinking with Types一书中, 6.4 Continuation Monad
告诉了类型a
和forall r. (a -> r) -> r
forall r. (a -> r) -> r
是同构的,可以通过以下函数来证明:
cont :: a -> (forall r. (a -> r) -> r)
cont x = \f -> f x
unCont :: (forall r. (a -> r) -> r) -> a
unCont f = f id
在这本书中,它告诉我们任何具有相同基数的两种类型总是彼此同构的。 所以我试图找出类型a
和forall r. (a -> r) -> r
的基数forall r. (a -> r) -> r
forall r. (a -> r) -> r
。
假设类型a
的基数是|a|
. 然后对于forall r. (a -> r) -> r
类型forall r. (a -> r) -> r
forall r. (a -> r) -> r
,如何算出它的基数等于|a|
? 函数类型a -> b
具有基数|b|^|a|
, 即|b|
到|a|
的力量 ,所以对于所有forall r. (a -> r) -> r
forall r. (a -> r) -> r
基数为|r|^(|r|^|a|)
。 怎么可能等于|a|
?
我糊涂了。 感谢您提供任何提示!
在多态类型存在的情况下,不能真正定义基数。 现在可以理解,多态类型“不是集合”,正如人们最初可能认为的那样。 雷诺兹在他的论文“多态不是集合论”中提供了一个著名的开创性论点,证明我们不能简单地以“平凡”的方式解释带有集合的类型并获得有意义的概念。
事实上,在集合中2^K
和K
是不同的基数,第一个更大。 同样, 2^(2^K)
大于K
。 然而, FX = 2^(2^X)
(类似于F a = (a -> Bool) -> Bool
)形成一个(协变)函子,我们可以找到一个不动点
newtype T = T ((T -> Bool) -> Bool)
获得T
与2^(2^T)
同构,这在集合中没有意义,正是因为它们不能具有相同的基数。
(即使没有递归类型,在存在多态的情况下,也可以通过forall a. (F a -> a) -> a
的编码获得上述类型T
)
无论如何,为了解决这个僵局,我们需要将a -> Bool
解释为不同于函数集2^a
其他东西。 一个可能的解决方案是使用Scott 连续函数,正如 Scott 所做的那样。 一个相关的解决方案是使用稳定函数(参见 Girard 的“证明和类型”一书),它(如果我没记错的话)使T
和T -> Bool
的解释具有相同的基数(除非两者都是有限的)。
因此,在存在多态类型的情况下,基数不是用于检查类型同构的正确工具。 我们真的需要看看是否可以像您在问题中发布的那样制作同构函数及其逆函数。
基数参数不适用于多态类型(请参阅@chi 的答案)。
但是同构本身可以这样直观地解释:
forall r. (a -> r) -> r
的类型forall r. (a -> r) -> r
forall r. (a -> r) -> r
意思是“如果你给我一个将a
转换为r
,我可以给你一个r
。哦,我可以为任何可能的r
做到这一点”
履行这样的承诺的唯一途径是通过秘密具有a
在我的手。
由于我承诺对任何可能的r
执行此操作,这意味着我对r
本身一无所知,包括如何构造它的值。 我唯一可用的是你给我的a -> r
函数。 调用这种函数的唯一方法是给它一个a
。
这意味着,如果我做出这样的承诺,我必须已经a
背后偷偷地做了a
。
对于更正式的解释,请回想一下,“同构”在普通术语中的意思是“可以明确地来回转换而不会丢失”。 这就是基数论证的意思:如果你有相同数量的东西,你总是可以在它们之间安排一个配对。
在您的问题中,您已经展示了两种转换: cont
一种方式转换, unCont
以另一种方式转换。 你可以简单地显示cont . unCont = unCont . cont = id
cont . unCont = unCont . cont = id
cont . unCont = unCont . cont = id
。 因此类型是同构的。
虽然显示两种转换的存在更正式,但我发现对于这两种类型如何真正“有点相同”的直觉并不总是令人满意,因此我在上面给出了直观的解释。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.