Haskell 在Ed Kmett';s递归方案包

Haskell 在Ed Kmett';s递归方案包,haskell,recursive-datastructures,recursion-schemes,fixpoint-combinators,Haskell,Recursive Datastructures,Recursion Schemes,Fixpoint Combinators,在Ed Kmett的递归方案包中,有三个声明: newtype Fix f = Fix (f (Fix f)) newtype Mu f = Mu (forall a. (f a -> a) -> a) data Nu f where Nu :: (a -> f a) -> a -> Nu f 这三种数据类型之间的区别是什么?Mu将递归类型表示为其折叠,而Nu将其表示为其展开。在Haskell中,这些是同构的,并且是表示同一类型的不同方式。如果假设Has

在Ed Kmett的
递归方案
包中,有三个声明:

newtype Fix f = Fix (f (Fix f))

newtype Mu f = Mu (forall a. (f a -> a) -> a)

data Nu f where 
  Nu :: (a -> f a) -> a -> Nu f

这三种数据类型之间的区别是什么?

Mu
将递归类型表示为其折叠,而
Nu
将其表示为其展开。在Haskell中,这些是同构的,并且是表示同一类型的不同方式。如果假设Haskell没有任意递归,那么这些类型之间的区别就变得更有趣了:
Mu f
f
的最小(初始)不动点,
Nu f
是其最大(终端)不动点

f
的不动点是
T
类型,是
T
ft
之间的同构,即一对逆函数
in::ft->T
out::T->ft
。类型
Fix
只是使用Haskell内置的类型递归直接声明同构。但是您可以为
Mu
Nu
实现in/out

举个具体的例子,假设您不能编写递归值。
Mu的居民可能
,即价值观
::对于所有r。(可能是r->r)->r
,是自然的,{0,1,2,…};
Nu的居民可能
,即值
::存在于x。(x,x->Maybe x)
,是自然数{0,1,2。。。,∞}. 想想这些类型的可能值,看看为什么
Nu可能有一个额外的居住者

如果您想对这些类型有一些直觉,那么在不递归的情况下实现以下内容(大致按照难度的增加顺序)可能是一个有趣的练习:

  • zeroMu::Mu Maybe
    succMu::Mu Maybe->Mu Maybe
  • zeroNu::Nu Maybe
    succNu::Nu Maybe->Nu Maybe
    inftyNu::Nu Maybe
  • muTofix::Mu f->Fix f
    fixToNu::Fix f->Nu f
  • inMu::f(muf)->muf
    outMu::muf->f(muf)
  • inNu::f(Nu-f)->Nu-f
    outNu::Nu-f->f(Nu-f)
您也可以尝试实现这些,但它们需要递归:

  • nuToFix::Nu f->Fix f
    fixToMu::Fix f->Mu f
Mu f
是最小的固定点,而
Nu f
是最大的固定点,因此编写函数
::Mu f->Nu f
非常容易,但编写函数
::Nu f->Mu f
很难,就像逆流而上一样


(有一次我想对这些类型写一个更详细的解释,但对于这种格式来说可能有点太长了。)

我不知道太多的理论,但我认为对于更多的证明语言,
Mu
是最小的不动点,
Nu
是最大的不动点。在Haskell中,这三者应该是等价的(我相信)。请注意,对于
Mu
Nu
来说,实现
cata
ana
非常容易。尝试解决这个问题是一个很好的解释,谢谢!是否有更详细的来源(文章/论文/书籍)来解释它?例如,术语级修复点的类比以及为什么Nu(作为其折叠的递归类型的表示)是类型级别上的最小不动点。LFP和初始代数之间以及GFP和终端余代数之间也存在着重要的联系。我肯定我遗漏了一些东西,但
Nu可能有更多的居民-至少有很多人喜欢Haskell类型检查。例如,
Nu Just[]
Nu Just“abcd”
Nu(无常数)42
似乎所有的类型都是正确的。我错了什么?等等。自然数?这是一件事吗?谢尔盖·切雷帕诺夫:我不知道一件事,不过这是用参数证明初始性的。初始代数和初始不动点之间的联系有时被称为兰贝克引理。B.梅塔:与id::for的方式相同所有a.a->a都无法区分不同的输入,外部世界无法区分Nu Just[]和Nu Just 0。paulotorrens:这至少是这种类型的惯用名称,自然的一点压缩,因此。感谢有趣的练习!如果有人感兴趣,我将我的答案上传到这里: