Haskell教会名单的运作

时间:2012-03-23 20:54:07

标签: haskell lambda-calculus church-encoding

我指的是this question

type Churchlist t u = (t->u->u)->u->u

在lambda演算中,列表编码如下:

[] := λc. λn. n
[1,2,3] := λc. λn. c 1 (c 2 (c 3 n))

mapChurch :: (t->s) -> (Churchlist t u) -> (Churchlist s u)
mapChurch f l = \c n -> l (c.f) n

我正在思考我可以在Churchlists上实现的其他列表函数,并成功编写了一个连接2个教会列表的conc2函数

conc2Church l1 l2 c n = l1 c (l2 c n)

我还尝试了一个zipWithChurch,它在普通列表中像zipWith一样运行。但我找不到解决方案。任何人都可以帮助我吗?

1 个答案:

答案 0 :(得分:4)

您想使用真正的元组还是教堂元组?我会假设前者。

因此,从所需的类型签名开始。您希望它接收2个不同的Churchlist并生成Churchlist个元组。

churchZip :: Churchlist a u -> Churchlist b u -> Churchlist (a,b) u

现在你将如何实现这个?回想一下,Churchlist由折叠它们的函数表示。因此,如果我们的结果是Churchlist (a,b) u,我们希望它具有类型((a,b) -> u -> u) -> u -> u的函数形式(毕竟,这相当于类型同义词Churchlist (a,b) u )。

churchZip l1 l2 c n = ???

下一步是什么?嗯,这取决于。 l1是空的吗?那么l2呢?如果其中任何一个是,那么您希望结果为空列表。否则,你想要对每个列表中的第一个元素进行配对,然后教会使用其他元素。

churchZip l1 l2 c n
  | isEmpty l1 || isEmpty l2 = n
  | otherwise                = c (churchHead l1, churchHead l2)
                                 (churchZip (churchTail l1) (churchTail l2) c n

这提出了一些问题。

  • 你是否可以递归写这个函数?在纯lambda演算中,您必须使用fixpoint运算符(也称为y组合子)编写递归函数。
  • 您有churchHeadchurchTailisEmpty吗?你愿意写吗?你能写出来吗?
  • 有没有更好的方法来构建这个功能?任何事情都可以通过折叠来完成(记住,l1l2实际上 折叠函数本身就是,但这是一个干净的解决方案吗?

如果对教会的名单编码有充分的了解,那么完全达到这一点是纯粹机械的。我会把深思熟虑留给你,因为这个作业。