Haskell 类型的连续传递样式表示法

Haskell 类型的连续传递样式表示法,haskell,continuations,continuation-passing,Haskell,Continuations,Continuation Passing,假设我们有一个单子,由return,(>=)和一组定律定义。有一种数据类型 newtype C m a = C { unC ∷ forall r. (a → m r) → m r } 也称为CMA≅ m a假设m是一个Monad,即我们可以编写两个函数∷ 单子m⇒ 我是→ C m a和来自∷ 单子m⇒ 文学硕士→ m a to ∷ Monad m ⇒ m a → C m a to t = C $ \f → t >>= f from ∷ Monad m ⇒ C m a → m a

假设我们有一个单子,由
return
(>=)
和一组定律定义。有一种数据类型

newtype C m a = C { unC ∷ forall r. (a → m r) → m r }
也称为<代码>CMA≅ m a假设
m
是一个
Monad
,即我们可以编写两个函数
∷ 单子m⇒ 我是→ C m a
来自∷ 单子m⇒ 文学硕士→ m a

to ∷ Monad m ⇒ m a → C m a
to t = C $ \f → t >>= f

from ∷ Monad m ⇒ C m a → m a
from = ($ return) . unC
并将
显示为∘ 从…起≡ id
来自∘ 到≡ id
通过等式推理,例如:

from . to =                                  -- by definition of `(.)'
  \x → from (to x) =                         -- by definition of `to'
  \x → from (C $ \f → x >>= f) =             -- by definition of `from'
  \x → ($ return) (unC (C $ \f → x >>= f)) = -- unC . C ≡ id
  \x → ($ return) (\f → x >>= f) =           -- β-reduce
  \x → x >>= return =                        -- right identity law
  \x → x =                                   -- by definition of `id'
  id
到目前为止还不错我的问题是

  • 给定一个类型和一系列规律,我们如何构造相应的同构CPS表示
  • 这个表示法是唯一的吗(我想不是)
  • 如果不是唯一的,是否总是有最“简单”(在
    s例如:))一个
这样的编码不是唯一的 当你提出这个问题时,答案显然是“不”

至于哪种编码是最小的……那么基本类型几乎可以肯定

共同性可能不是你想要的 更重要的是,虽然Codensity很吸引人,但我不相信它与底层类型是同构的<代码>从。to=id
是一个简单的方向

to . from
  = \x -> to (from x)
  = \x -> C $ \f -> (from x) >>= f
  = \x -> C $ \f -> (unC x return) >>= f
  = \(C g) -> C $ \f -> (g return) >>= f
但是你会被卡住。当你试图证明
a=forall r时,同样的事情也会发生。(a->r)->r
但是你被“免费定理”所拯救(没有这个可能有办法,但是免费定理让它变得容易)。我不知道关于代码性的相应论据,我读过的大多数论文都证明它保留了
>=
返回
,也就是说,如果你只使用一元运算和你所称的
to
构造你的
CMA
,那么对
to的调用。from
是标识

如果我们足够努力,我们甚至可以想出一个同构的反例

evil :: C Maybe Int
evil = C $ \h -> case h 1 of
                      Nothing -> h 2
                      Just x  -> Nothing


 to . from $ evil
  = (\(C g) -> C $ \f -> (g return) >>= f) evil
  = C $ \f -> ((\h -> case h 1 of
                      Nothing -> h 2
                      Just x  -> Nothing) return) >>= f
  = C $ \f -> Nothing >>= f
那么这些是相同的吗

test 1 = Nothing
test n = Just n

unC evil test
  = Just 2
unC (C $ \f -> Nothing >>= f) test
  = Nothing >>= test
  = Nothing
我可能在推导过程中犯了一个错误。我还没有真正检查过它,但现在我只想说我不认为
cma=ma

to ∷ Monad m ⇒ m a → C m a
to t = C $ \f → t >>= f

from ∷ Monad m ⇒ C m a → m a
from = ($ return) . unC
另一种CPS 所有数据都可以编码为非类型的lambda函数,Church大约在70年前发现了这一特性。我们经常谈论“Church编码”数据结构,尽管Oleg建议,至少在类型化设置中,我们应该讨论“Boehm Beraducci”编码。不管你怎么称呼它,这个想法是

(a,b) = forall r. (a -> b -> r) -> r
Either a b = forall r. (a -> r) -> (b -> r) -> r
至少是快速和松散的推理。显然,这种编码提供了一种将任何ADT编码为System F类型的方法。这还揭示了一种实现函数式语言的方法:将所有内容都视为隐藏的闭包,并将模式匹配作为函数应用程序来实现

实际上,系统F甚至有一种将存在类型编码为通用类型的方法

exists a. f a = forall r. (forall a'. f a' -> r) -> r

这是一个非常重要的身份。除此之外,这有助于我们思考高阶类型和存在类型的类型推理之间的关系。由于类型推理最多可判定为秩2类型,因此类型推理在具有秩1共性和存在性的系统中也是可判定的。因为存在量化是模块的基础,这是很重要的

我的大脑跑掉了,你吓坏了。一般来说,任何类型的
a
都相当于
(对于所有的r.(a->r)->r)
。但是这不是很有趣。考虑一些有趣的事情:取消你给
(,)
的编码,或者
会导致
((a,b)->r)->r
(a->r,b->r)->r
。这些与
(a b->r)->r
(a->r)(b->r)->r
有何不同?我同意!(看起来很有趣)哦,我应该查一下。过帐前从
☹. 不管怎样,回答很好,谢谢。