问题标签 [recursion-schemes]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
recursion-schemes - 代数接收项目位置的态射
当转换器函数中需要给定项目的位置(索引或路径)时,使用哪一个是合适的态射(递归方案)?
一个简单的示例是将列表["foo", "bar", "qux"]
转换为字符串"foo, bar, and qux"
。需要当前元素的位置来知道何时插入and
.
functional-programming - 如何证明 Church 编码,forall r。(F r -> r) -> r,给出函子 F 的初始代数?
自然数的著名 Church 编码可以推广到使用任意函子F
。结果是类型,称为它C
,定义为
在这里和下面,为简单起见,我们将假设它F
是一个固定的、已经定义的函子。
众所周知,类型C
是函子的固定点F
,也是C
初始F
代数。例如,如果函子F a
定义为
然后是F a
is的固定点[a]
(类型的值列表a
)。另外,[a]
是初始代数。列表的 Church 编码是众所周知的。但是我找不到这些陈述中的任何一个的严格证明(C
是一个固定点,并且C
是初始代数)。
问题是,如何严格证明两个陈述之一:
- 该类型
C
是类型 isomorphism 的固定点F C ≅ C
。换句话说,我们需要证明存在两个函数,fix :: F C -> C
并且unfix :: C -> F C
使得fix . unfix = id
和unfix . fix = id
。 - 类型
C
是函子的初始代数F
;即-F
代数范畴中的初始对象。换句话说,对于任何给定A
函数p :: F A -> A
的类型(即是-A
代数F
),我们都可以找到一个唯一的函数q :: C -> A
,它是 F-代数态射。这意味着,q
必须使法律q . fix = p . fmap q
成立。我们需要证明,给定A
和p
,这样q
的存在并且是唯一的。
这两个语句不等价;但证明(2)意味着(1)。(Lambek 定理说初始代数是同构。)
fix
函数的代码unfix
可以相对容易地编写:
给定一个函数p :: F A -> A
,函数的代码q
写成
然而,似乎很难直接证明函数fix
, unfix
,q
满足所需的性质。我找不到完整的证明。
C
证明它是一个初始代数,即它q
是唯一的,比证明它更容易fix . unfix = id
吗?
在这个问题的其余部分,我将展示一些我能够为证明fix . unfix = id
.
仅通过使用给定的函数代码来证明 (1) 或 (2) 是不可能的。我们需要额外的假设。与米田身份相似,
我们需要假设函数的代码是完全参数化的(没有副作用,没有特别选择的值或固定类型),以便可以应用参数化定理。所以,我们需要假设类型只包含满足适当自然法则C
的类型函数。forall r. (F r -> r) -> r
参数化定理为这种类型签名给出了以下自然法则:对于任何类型A
and B
,以及对于任何函数p :: F B -> A
and f :: A -> B
,函数c :: forall r. (F r -> r) -> r
必须满足等式
Using this naturality law with appropriately chosen p
and f
, one can show that the composition fix . unfix
is a certain function of type C -> C
that must be equal to \c -> (run c) fix
.
然而,证明的进一步进展似乎是不可能的。不清楚为什么这个函数必须等于id
。
让我们暂时定义函数m
:
然后我得到的结果写成
也可以证明这一点unfix . fix = fmap (m fix)
。
这还有待证明m fix = id
。一旦证明了这一点,我们就证明了F C ≅ C
。
相同的自然规律c
与不同的选择p
并f
赋予了奇怪的身份
但不知如何从这个身份中推导出来m fix = id
。
idris - 如何在 Idris2 中编写 CV-Coalgebra?
在 Haskell 中,我可以写
但 Idris 似乎不允许使用data
. 他们确实合作record
,即我可以写作
但是如果我理解正确的话,我不能有多个变体。有解决办法吗?
haskell - 是否可以使用(共)递归创建有效的重组树?
通过共同递归,我的意思是展开一棵树,例如使用ana
Ed Kmett递归方案中的态射
通过重新组合树,我的意思是共享结构的图。例如,二项式期权定价树或帕斯卡三角形。这两者都有一些对称性,所以为了效率,我们希望避免重新计算树的一部分,而是重新使用已经计算过的分支。
注意这个问题不是关于计算上述示例中的值的一些聪明方法;这是关于递归的一般问题。
例如,对于期权定价,可以像这样生成树:
因此,“向上”分支中p * x
的值为 ,“向下”分支中的值为(1-p) * x
。由于这种对称性,“up”后跟“down”节点将具有与“down”后跟“up”分支相同的值。它也是整个子树。
我认为有可能以State
某种方式传递包含已计算节点的哈希图。
或者,如果我能以某种方式访问已经计算过的子树,我可以将它作为态射中的 aLeft
传入apo
。
是否有一些现有的态射允许这样做?或者我可以自己编码吗?
haskell - 递归方案允许递归调用之间的依赖关系(有序的变态?)
我对编写递归代码的高阶方式(递归方案)感兴趣,其中递归调用之间可能存在依赖关系。
作为一个简化的例子,考虑一个遍历整数树的函数,检查总和是否小于某个值。我们可以对整棵树求和,并将其与最大值进行比较。或者,我们可以在超过最大值后立即保持运行总和并短路:
有没有办法用递归方案来表达这个想法——本质上是一个有序的遍历?我对尽可能一般地编写这样的有序遍历感兴趣。
理想情况下,我想要某种方式来编写遍历,其中在数据结构上折叠(或展开)的函数决定了遍历的顺序。无论我最终得到什么抽象,我都希望能够编写sumLT'
上面遍历的逆序版本,而不是从右到左:
recursion - 如何解决这个间接递归错误?
对于此代码,我收到以下错误:
对于这个简单的间接递归示例,可能的错误是什么?我什至尝试改变函数的顺序。
functional-programming - 你能用 Mendler 式的变形写一个无限循环吗?
如果我们有一个函子固定点:
Fix f = Con (f (Fix f))
then 该函数out : Fix f -> f (Fix f)
使用起来不安全,因为 if f
is not a Functor
then 您可以轻松编写无限循环(例如 with f x = x -> x
)。
我的问题:如果我们只能Fix
用 Mendler 式的超态来消除(即使f
不是 a Functor
),是否可以编写一个无限循环?
对于 Mendler 式的超态,我正在考虑以下类型:
我的预感是答案是否定的,因为我们只能写out
iff
实际上是一个函子:
所以这意味着它mpara
可以安全地与任何f
. 我对么?
parsing - 具有变形的 Haskell monadic 解析器
我的问题是如何将递归的 F 代数风格的递归类型定义与单子/应用风格的解析器结合起来,以适应现实的编程语言。
我刚刚从以下Expr
定义开始:
我正在尝试将它与使用变形的解析器结合起来:
据我所知,在我的示例中,psi
应该只解析一个整数,或者它应该确定字符串是 a<expr> + <expr>
然后(通过递归调用fmap (ana psi)
),它应该解析左侧和右侧表达式.
但是,(monadic/applicative)解析器不是这样工作的:
- 他们首先尝试解析左边的表达式,
+
, _- 和右手表达式
我看到的一种解决方案是更改 to 的类型定义,Plus a a
以便Plus Integer a
它反映解析过程,但这似乎不是最好的途径。
欢迎任何建议(或阅读指导)!
haskell - 在递归方案中组成非分布式单子
关于 Haskell 中的递归方案,我最喜欢的事情之一是广义态射(gcata
等),它允许使用 monad 转换器库来交叉(co-)monadic 计算与递归。例如,如这篇精彩的博客文章中所述。
但是,我遇到了一个问题;为了能够使用这些函数,我们需要 (co-)monads 是 (co-)sequentiable。考虑一个类型签名gana
:
第一个参数本质上说m
必须有一个sequence
运算符。
不幸的是,我发现在实践中,有些单子不是可分配的。例如:
- 表示数据库事务的 monad。中止时,事务可以回滚;如果已排序,则只能回滚到已排序的点。
- 一个并发单子,表示资源上的锁或原子计算。排序后,锁会暂时丢失。
在这种情况下,仍然可以编写一个专门的递归方案来交错单子执行;但是你失去了使用单子变压器融合它的能力。即,如果你想组合这样的非分配单子,它们不能使用变压器与 f-(co) 代数中的单子/共单子进行融合。具体来说,我不能使用 monad 转换器将DBTransaction
monad 与 apomorphism ( ExceptT/EitherT
) 结合起来;我需要从头开始编写自定义递归方案。
我的问题是是否有人有解决此限制的建议。