让我们从熟悉的CPS暂停计算类型(a -> r) -> r
开始,拼写为 mtl -speak中的Cont r a
。我们知道it is isomorphic to a
as long as it is kept polymorphic in r
。如果我们嵌套这种类型,我们得到这个rank-3类型:
forall r. ((forall s. (a -> s) -> s) -> r) -> r
(为了方便起见,我可能已定义type Susp a = forall r. (a -> r) -> r
,然后开始讨论Susp (Susp a)
,但我担心这会导致分散注意力的技术问题。)
我们可以通过在嵌套之后普遍量化结果类型来获得类似的类型,就像我们有forall r. Cont r (Cont r a)
一样:
forall r. (((a -> r) -> r) -> r) -> r
这两种类型之间有什么有意义的区别吗?我说有意义,因为有些事情显然只能用第一种“SuspSusp”类型完成......
GHCi> foo = (\kk -> kk (\k -> k True)) :: forall s. ((forall r. (Bool -> r) -> r) -> s) -> s
GHCi> bar = (\kk -> kk (\k -> k True)) :: forall r. (((Bool -> r) -> r) -> r) -> r
GHCi> foo (\m -> show (m not))
"False"
GHCi> bar (\m -> show (m not))
<interactive>:76:12: error:
* Couldn't match type `[Char]' with `Bool'
Expected type: Bool
Actual type: String
* In the expression: show (m not)
In the first argument of `bar', namely `(\ m -> show (m not))'
In the expression: bar (\ m -> show (m not))
...也可以通过第二个“ContCont”来实现,利用任何(a -> r) -> r
的{{1}},f (m g) = m (f . g)
的自由定理。
m :: (a -> r) -> r
答案 0 :(得分:1)
(部分答案)
如果a
出现与您提议的类型同构,我不会感到惊讶
forall r. (((a -> r) -> r) -> r) -> r
到目前为止,我只能证明前者嵌入后者。嵌入也可以是同构,但是如果这种情况成立,则证明我们可能需要在上面的可怕类型上利用参数化。
这是嵌入:
type YD a = forall r. (((a -> r) -> r) -> r) -> r
ydosi :: a -> YD a
ydosi x = \f -> f (\g -> g x)
ydiso :: YD a -> a
ydiso x = x (\a -> a id)
证明这是一个嵌入很容易,只需要beta步骤:
ydiso (ydosi x)
= ydiso (\f -> f (\g -> g x))
= (\f -> f (\g -> g x)) (\a -> a id)
= (\a -> a id) (\g -> g x)
= (\g -> g x) id
= id x
= x
相反的方向要困难得多,并且(如果可能的话)应该依赖x :: YD a
的参数。完成此操作将证明所需的同构性。
ydosi (ydiso x)
= ydosi (x (\a -> a id))
= \f -> f (\g -> g (x (\a -> a id)))
= ????
= x
答案 1 :(得分:1)
我对以下事情并不完全有信心(有点感觉太好了),但这是我迄今为止提供的最好的,所以让我们把它放在桌面上。
chi's answer通过在a
和forall r. (((a -> r) -> r) -> r) -> r
之间提出同构候选来解决问题:
-- If you want to play with these in actual code, make YD a newtype.
type YD a = forall r. (((a -> r) -> r) -> r) -> r
ydosi :: a -> YD a
ydosi x = \kk -> kk (\k -> k x)
ydiso :: YD a -> a
ydiso mm = mm (\m -> m id)
chi然后证明ydiso . ydosi = id
,这使得ydosi . ydiso
方向得以处理。
现在,如果我们有一些f
及其左反g
(g . f = id
),则很容易遵循f . g . f = f
。如果f
是满射的,我们可以在右边“取消”它,导致我们f . g = id
(即同构的另一个方向)。既然如此,鉴于我们有ydiso . ydosi = id
,确定ydosi
是完全的,将足以证明同构。研究这一问题的一种方法是对YD a
的居民进行推理。
(虽然我不会在这里尝试这样做,但我认为通过根据System F输入规则表达它们可以使以下段落更精确 - cf. this Math.SE question。)
YD A
值是一个延续的函数:
mm :: forall r. (((A -> r) -> r) -> r) -> r
mm = \kk -> _y
-- kk :: forall r. ((A -> r) -> r) -> r
-- _y :: r
在此处获取r
类型结果的唯一方法是将kk
应用于某些内容:
mm :: forall r. (((A -> r) -> r) -> r) -> r
mm = \kk -> kk _m
-- kk :: forall r. ((A -> r) -> r) -> r
-- _m :: forall r. (A -> r) -> r
由于kk
中r
的类型是多态的,因此必须是_m
的类型。这意味着我们也知道_m
必须是什么样的,感谢熟悉的A
/ forall r. (A -> r) -> r
同构:
mm :: forall r. (((A -> r) -> r) -> r) -> r
mm = \kk -> kk (\k -> k _x)
-- kk :: forall r. ((A -> r) -> r) -> r
-- k :: forall r. (A -> r) -> r
-- _x :: A
然而,上面的右侧恰好是ydosi
:
mm :: forall r. (((A -> r) -> r) -> r) -> r
mm = ydosi _x
-- _x :: A
我们刚发现某些forall r. (((A -> r) -> r) -> r) -> r
的{{1}}值ydosi x
为x :: A
。紧接着ydosi
是完全的,这足以证明同构。
由于a
与forall r. ((forall s. (a -> s) -> s) -> r) -> r
(参见Twan van Laarhoven's comment)和forall r. (((a -> r) -> r) -> r) -> r
同构,因此传递性意味着两种嵌套悬架类型都是同构的。
嵌套悬架同构的见证是什么样的?如果我们定义......
-- The familiar isomorphism.
type Susp a = forall r. (a -> r) -> r
suosi :: a -> Susp a
suosi x = \k -> k x
suiso :: Susp a -> a
suiso m = m id
......我们可以写......
ydosi . suiso . suiso :: Susp (Susp a) -> YD a
suosi . suosi . ydiso :: YD a -> Susp (Susp a)
...归结为:
-- A few type annotations would be necessary to persuade GHC about the types here.
\mm -> \kk -> kk (\k -> k (mm id id)) -- Susp (Susp a) -> YD a
\mm -> \kk -> kk (\k -> k (mm (\m -> m id))) -- YD a -> Susp (Susp a)
我们可以在第一位见证人Susp a
上应用mm
自由定理......
f (mm g) = mm (f . g) -- Free theorem
f (mm id) = mm f
mm id id
($ id) (mm id)
mm ($ id)
mm (\m -> m id)
......等等:
\mm -> \kk -> kk (\k -> k (mm (\m -> m id))) -- Susp (Susp a) -> YD a
\mm -> \kk -> kk (\k -> k (mm (\m -> m id))) -- YD a -> Susp (Susp a)
令人着迷的是,除了他们的类型之外,证人是“相同的”。我想知道从这个观察开始是否有一些争论会让我们倒退并以更直接的方式证明同构。