当前位置: 首页 > 知识库问答 >
问题:

如何有效地将归纳类型转换为共归纳类型(无需递归)?

呼延英奕
2023-03-14
> {-# LANGUAGE DeriveFunctor, Rank2Types, ExistentialQuantification #-}

任何归纳类型都是这样定义的

> newtype Ind f = Ind {flipinduct :: forall r. (f r -> r) -> r}
> induction = flip flipinduct

归纳具有类型(f a->a)->Ind f->a。对此有一个双重概念,叫做共感应。

> data CoInd f = forall r. Coinduction (r -> f r) r
> coinduction = Coinduction

共感应具有(a->f a)->a->CoInd f类型。注意归纳共归纳是如何对偶的。作为归纳和共归纳数据类型的示例,请看这个函式。

> data StringF rec = Nil | Cons Char rec deriving Functor
> wrap :: (Functor f) => f (CoInd f) -> CoInd f
> wrap fc = coinduction igo Nothing where
>   --igo :: Maybe (CoInd f) -> f (Maybe (CoInd f))
>   igo Nothing  = fmap Just fc
>   igo (Just (Coinduction step seed)) = fmap (Just . Coinduction step) $ step seed
> convert :: (Functor f) => Ind f -> CoInd f
> convert = induction wrap
> cowrap :: (Functor f) => Ind f -> f (Ind f)
> cowrap = induction igo where
>    --igo :: f (f (Ind f)) -> f (Ind f)
>    igo = fmap (\fInd -> Ind $ \fold -> fold $ fmap (`flipinduct` fold) fInd)

归纳总是O(n)cowrap也是如此。

我们可以使用cointensioncowrapind f生成coind f

> convert' :: (Functor f) => Ind f -> CoInd f
> convert' = coinduction cowrap

这也是每次我们获得一个元素时O(n),总共O(n^2)

我的问题是,如果不使用递归(直接或间接),我们能否在O(n)时间内将ind f转换为coind f

我知道如何使用递归(将ind f转换为fix f,然后将fix f转换为O(n)(初始转换是O(n),但随后coind f)中的每个元素都是O(1),使得第二次转换O(n)total和O(n)+O(n)=O(n)),但我想看看是否可以不这样做。

注意convertconvert'从未直接或间接地使用递归。很漂亮,不是吗!

共有1个答案

充修能
2023-03-14

是的,这在形式上是可能的:

https://github.com/jyp/controlledfusion/blob/master/control/fixpoints.hs

但是,转换仍然需要在运行时构造中间缓冲区,这只能使用循环来完成。

 类似资料:
  • HList是共感的吗?如果是,一个共感类型如何包含有限值? 如果我们定义呢?这会被认为是什么和/或它会比有用吗?

  • 问题内容: 我是Go编程语言的新手,我有一个创建和解释器的任务,但是我遇到了以下问题: 我想将环境定义为: 但是我收到错误“无效的递归类型环境”。根据我的研究,我将父级更改为 Environment。但是现在,当我需要创建一个环境类型为var的新环境时,它会收到错误消息“无法将fun_Val.ds(环境类型)用作 环境值类型”。我正在如下创建环境: 我试图将这篇文章中的代码量限制在一定范围内,但是

  • 我有一个关于如何将“递归”转换为“尾部递归”的问题。 这不是家庭作业,只是在我试图润色算法书籍中的递归定理时出现的一个问题。 我熟悉使用递归的两个典型示例(阶乘和斐波那契序列),也知道如何以递归方式和尾部递归方式实现它们。 我的代码如下(我使用Perl只是为了使其简单,但可以轻松地转换为C/Java/C)。 运行代码时,输出如下: 递归函数在返回之前使用不同的参数调用自己两次。我尝试了几种方法将其

  • 计算机的威力源自其反复执行同一任务或同一任务不同版本的能力。在计算领域,迭代这一主题会以多种形式出现。数据模型中的很多概念(比如表)都是某种形式的重复,比如“表要么为空,要么由一个元素接一个元素,再接一个元素,如此往复而成”。使用迭代,程序和算法可以在不需要单独指定大量相似步骤的情况下,执行重复性的任务,如“执行下一步骤1000次”。编程语言使用像C语言中的while语句和for语句那样的循环结构

  • 问题 你有一个对象数组,想要把它们归纳为一个值,类似于 Ruby 中的 reduce() 和 reduceRight() 。 解决方案 可以使用一个匿名函数包含 Array 的 reduce() 和 reduceRight() 方法,保持代码清晰易懂。这里归纳可能会像对数值和字符串应用 + 运算符那么简单。 [1,2,3,4].reduce (x,y) -> x + y # => 10 ["wo

  • 查看我在某处(这里是游乐场)找到的这个Typescript4.2片段: 我的头不能绕着它。TS如何处理这件事?它怎么不卡在无限递归里?具体地说,对于和的情况,悬停在变量上显示TS将类型解析为和。这是怎么回事?