许多变形似乎很简单,主要是用一个定制功能代替每个数据构造函数,例如。
data Bool = False | True
foldBool :: r              -- False constructor
         -> r              -- True constructor
         -> Bool -> r

data Maybe a = nothing | Just a
foldMaybe :: b             -- nothing constructor
          -> (a -> b)      -- Just constructor
          -> Maybe a -> b

data List a = Empty | Cons a (List a)
foldList :: b              -- Empty constructor
         -> (a -> b -> b)  -- Cons constructor
         -> List a -> b

然而,对我来说不清楚的是,如果使用相同的类型构造函数,但是使用不同的类型参数会发生什么。例如。而不是将列表a传递给Cons,那怎么办?

data List a = Empty | Cons a (List (a,a))

或者,也许是一个更疯狂的情况:

data List a = Empty | Cons a (List (List a))
foldList :: b              -- Empty constructor
         -> ???            -- Cons constructor
         -> List a -> b

我有两个合理的想法部分是

(a→b→b),即递归地替换List构造函数的所有应用程序)
>(a – >列表b – > b),即仅替换所有列出应用程序。

哪两个是正确的,为什么?还是不一样呢?

这只是部分答案。

OP提出的问题是:如果在非常规递归类型的情况下如何定义fold / cata?

既然我不相信自己这个权利,我会诉诸于要求Coq。我们从一个简单的,常规的递归列表类型开始。

Inductive List (A : Type) : Type :=
  | Empty: List A
  | Cons : A -> List A -> List A
.

在这里没有什么想法,列表A是用List A来定义的。
(记住这一点 – 我们会回头看看。)

cata怎么样?让我们来看一下感应线。

> Check List_rect.
forall (A : Type) (P : List A -> Type),P (Empty A) ->
   (forall (a : A) (l : List A),P l -> P (Cons A a l)) ->
   forall l : List A,P l

让我们来看看。上述漏洞依赖类型:P取决于列表的实际值。在P列表是常数类型B的情况下,我们只需手动简化。我们获得:

forall (A : Type) (B : Type),B ->
   (forall (a : A) (l : List A),B -> B) ->
   forall l : List A,B

这可以等同地写成

forall (A : Type) (B : Type),B ->
   (A -> List A -> B -> B) ->
   List A -> B

哪个是折叠,除了“当前列表”也传递给二进制函数参数 – 不是主要区别。

现在,在Coq中,我们可以用另一种微妙的方式定义一个列表:

Inductive List2 : Type -> Type :=
  | Empty2: forall A,List2 A
  | Cons2 : forall A,A -> List2 A -> List2 A
.

它看起来是一样的,但是有一个深刻的区别。这里我们没有按照List A定义类型List A.而是我们定义一个类型函数List2:Type – >用List2来输入。其主要目的是对List2的递归引用不必适用于A – 事实上,我们这样做只是一个事件。

无论如何,让我们看看引入原理的类型:

> Check List2_rect.
forall P : forall T : Type,List2 T -> Type,(forall A : Type,P A (Empty2 A)) ->
   (forall (A : Type) (a : A) (l : List2 A),P A l -> P A (Cons2 A a l)) ->
   forall (T : Type) (l : List2 T),P T l

我们像以前一样从P中删除List2 T参数,基本上假定P是恒定的。

forall P : forall T : Type,Type,P A ) ->
   (forall (A : Type) (a : A) (l : List2 A),P A -> P A) ->
   forall (T : Type) (l : List2 T),P T

同等重写:

forall P : (Type -> Type),P A) ->
   (forall (A : Type),A -> List2 A -> P A -> P A) ->
   forall (T : Type),List2 T -> P T

在Haskell符号中大致对应

(forall a,p a) ->                          -- Empty
(forall a,a -> List2 a -> p a -> p a) ->   -- Cons
List2 t -> p t

不错 – 基本情况现在必须是一个多态函数,就像Haskell中的空格一样。这有道理类似地,归纳情况必须是多态函数,就像缺点一样。有一个额外的List2一个参数,但是我们可以忽略,如果我们想要的话。

现在,上面的一种是常规类型的fold / cata。非常规的呢?我会学习

data List a = Empty | Cons a (List (a,a))

在Coq中成为:

Inductive  List3 : Type -> Type :=
  | Empty3: forall A,List3 A
  | Cons3 : forall A,A -> List3 (A * A) -> List3 A
.

具有感应原理:

> Check List3_rect.
forall P : forall T : Type,List3 T -> Type,P A (Empty3 A)) ->
   (forall (A : Type) (a : A) (l : List3 (A * A)),P (A * A) l -> P A (Cons3 A a l)) ->
   forall (T : Type) (l : List3 T),P T l

删除“依赖”部分:

forall P : (Type -> Type),A -> List3 (A * A) -> P (A * A) -> P A ) ->
   forall (T : Type),List3 T -> P T

在Haskell符号:

(forall a. p a) ->                                      -- empty
   (forall a,a -> List3 (a,a) -> p (a,a) -> p a ) ->    -- cons
   List3 t -> p t

除了附加的List3(a,a)参数外,这是一种折叠。

最后,OP类型呢?

data List a = Empty | Cons a (List (List a))

唉,Coq不接受这种类型

Inductive  List4 : Type -> Type :=
  | Empty4: forall A,List4 A
  | Cons4 : forall A,A -> List4 (List4 A) -> List4 A
.

因为内部的List4的出现不是在严格正确的位置。这可能是一个暗示,我应该停止懒惰和使用Coq来完成这项工作,并开始考虑自己涉及的F代数…

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

haskell – 非正则递归类型的变形(折叠)的类型是什么?的更多相关文章

  1. ios – 嵌套递归函数

    我试图做一个嵌套递归函数,但是当我编译时,编译器崩溃.这是我的代码:编译器记录arehere解决方法有趣的…它似乎也许在尝试在定义之前捕获到内部的引用时,它是bailing?以下修复它为我们:当然没有嵌套,我们根本没有任何问题,例如以下工作完全如预期:我会说:报告!

  2. swift override --有一个递归问题未解决

    classca{varcount:Int{get{return1;}set{self.count=newValue;}}funcdescribe()->String{return"ca";}}classcb:ca{overridefuncdescribe()->String{return"cb";}overridevarcount:Int{get{return2;}set{//引起了递归调用,未找

  3. Swift2.0语言教程之函数嵌套调用形式

    Swift2.0语言教程之函数嵌套调用形式Swift2.0语言函数嵌套调用形式在Swift中,在函数中还可以调用函数,从而形成嵌套调用。以下将对这两种调用进行详细讲解。调用方式如图7.4所示。图7.4函数嵌套的形式以下将使用函数的嵌套调用实现对s=22!这个数值,即调用f1()函数,计算22,结果为4,然后在调用f2()函数,对4的阶乘求取,计算完成22!但是在Swift语言中递归必须要有一个满足结束的条件。

  4. 【Swift】学习笔记(九)——枚举

    因为类完全可以替代枚举。不过swift中也有许多类的特性被枚举支持。这样判断必须穷举所有成员,否则就需要增加default这个选项了。使用递归枚举时,编译器会插入一个中间层。

  5. Swift实现的快速排序及sorted方法的对比

    Swift语言有着优秀的函数式编程能力,面试的时候面试官都喜欢问我们快速排序,那么用Swift如何实现一个快速排序呢?然后实现快速排序的方法:可以发现使用Swift实现快速排序的代码非常的简洁。在看完这段代码后我做了如下思考:既然是排序,那么必然可以使用系统的sorted方法,效果如何呢?对于快排最头疼的顺序性数组,sorted的重复次数只有n次!说明在面对这种类型的数组的时候sorted方法进行过判断,直接输出了。

  6. 《swift2.0 官方教程中文版》 第2章-08枚举

    importFoundation//在Swift中,枚举类型是一等公民。像Swift中其他类型一样,它们的名字必须以一个大写字母开头。给枚举类型起一个单数名字而不是复数名字,以便于读起来更加容易理解:vardirectionToHead=Compasspoint.West//directionToHead的类型可以在它被Compasspoint的一个可能值初始化时推断出来。//使用枚举成员的rawValue属性可以访问该枚举成员的原始值:letearthsOrder=Planet2.Earth.rawVa

  7. swift枚举

    Swift中的枚举更加灵活,不必给每一个枚举成员提供一个值。它是Directionoperation类型,因为swift中的枚举不会自动给成员赋值为0,1…枚举类型易扩展。原始值的隐式赋值在使用原始值为整数或者字符串类型的枚举时,不需要显式地为每一个枚举成员设置原始值,Swift将会自动为你赋值。

  8. Swift学习之路04-枚举

    枚举在Swift中,枚举类型是一等类型。*注意与C和Objective-C不同,Swift的枚举成员在被创建时不会被赋予一个默认的整型值。在上面的nt例子中,north,East和West不会被隐式地赋值为0,1,2和3。相反,这些枚举成员本身就是完备的值,这些值的类型是已经明确定义好的Compasspoint类型。下面的例子是Compasspoint枚举的细化,使用字符串类型的原始值来表示各个方向的名称:上面例子中,Compasspoint.south拥有隐式原始值South,依次类推。使用递归枚举时,

  9. The Swift Programming Language学习笔记九——枚举

    Swift中的枚举更加灵活,不必给每一个枚举成员提供一个值。在Swift中,枚举类型是一等类型。注意,与C和Objective-C不同,Swift的枚举成员在被创建时不会被赋予一个默认的整型值。使用let和var定义枚举常量和变量。使用switch语句匹配枚举值使用switch语句匹配单个枚举值。强制穷举确保了枚举成员不会被意外遗漏。枚举的这种特性跟其他语言中的可识别联合,标签联合,或者变体相似。使用枚举成员的rawValue属性可以访问该枚举成员的原始值。

  10. Swift讲解专题九——枚举

    Swift讲解专题九——枚举一、引言在Objective-C语言中,没有实际上是整型数据,Swift中的枚举则更加灵活,开发者可以不为其分配值类型把枚举作为独立的类型来使用,也可以为其分配值,可以是字符,字符串,整型或者浮点型数据。

随机推荐

  1. 法国电话号码的正则表达式

    我正在尝试实施一个正则表达式,允许我检查一个号码是否是一个有效的法国电话号码.一定是这样的:要么:这是我实施的但是错了……

  2. 正则表达式 – perl分裂奇怪的行为

    PSperl是5.18.0问题是量词*允许零空间,你必须使用,这意味着1或更多.请注意,F和O之间的空间正好为零.

  3. 正则表达式 – 正则表达式大于和小于

    我想匹配以下任何一个字符:或=或=.这个似乎不起作用:[/]试试这个:它匹配可选地后跟=,或者只是=自身.

  4. 如何使用正则表达式用空格替换字符之间的短划线

    我想用正则表达式替换出现在带空格的字母之间的短划线.例如,用abcd替换ab-cd以下匹配字符–字符序列,但也替换字符[即ab-cd导致d,而不是abcd,因为我希望]我如何适应以上只能取代–部分?

  5. 正则表达式 – /bb | [^ b] {2} /它是如何工作的?

    有人可以解释一下吗?我在t-shirt上看到了这个:它似乎在说:“成为或不成为”怎么样?我好像没找到’e’?

  6. 正则表达式 – 在Scala中验证电子邮件一行

    在我的代码中添加简单的电子邮件验证,我创建了以下函数:这将传递像bob@testmymail.com这样的电子邮件和bobtestmymail.com之类的失败邮件,但是带有空格字符的邮件会漏掉,就像bob@testmymail也会返回true.我可能在这里很傻……当我测试你的正则表达式并且它正在捕捉简单的电子邮件时,我检查了你的代码并看到你正在使用findFirstIn.我相信这是你的问题.findFirstIn将跳转所有空格,直到它匹配字符串中任何位置的某个序列.我相信在你的情况下,最好使用unapp

  7. 正则表达式对小字符串的暴力

    在测试小字符串时,使用正则表达式会带来性能上的好处,还是会强制它们更快?不会通过检查给定字符串的字符是否在指定范围内比使用正则表达式更快来强制它们吗?

  8. 正则表达式 – 为什么`stoutest`不是有效的正则表达式?

    isthedelimiter,thenthematch-only-onceruleof?PATTERN?

  9. 正则表达式 – 替换..与.在R

    我怎样才能替换..我尝试过类似的东西:但它并不像我希望的那样有效.尝试添加fixed=T.

  10. 正则表达式 – 如何在字符串中的特定位置添加字符?

    我正在使用记事本,并希望使用正则表达式替换在字符串中的特定位置插入一个字符.例如,在每行的第6位插入一个逗号是什么意思?如果要在第六个字符后添加字符,请使用搜索和更换从技术上讲,这将用MatchGroup1替换每行的前6个字符,后跟逗号.

返回
顶部