数学与计算

关于计算机数学的博客

看似不可能的功能程序

安德烈邀请我写一些令人惊讶的功能程序。第一个程序,由于乌尔里希·伯杰(1990),执行详尽搜索“康托尔空间“二进制无限序列数字。我在末尾加入了参考资料。弱形式的穷举搜索相当于检查是否存在总谓词包含康托空间的所有元素。因此,这相当于康托空间上的通用量化。这可能是吗在有限时间内完成算法?

更强的相当于找到一个谓词成立的示例,如果是这样的示例存在,并说没有其他的。

我会使用语言哈斯克尔,但有可能快速将程序转换为ML或OCaml公司。此处显示的源代码附加为似乎不太可能。hs.

我们可以使用布尔值来表示二进制数字,甚至可以使用整数,但我更喜欢使用不同的类型以避免混淆:

>data位=零|一>推导(等式)

这个衍生子句告诉Haskell找出如何自动决定位的相等性。

对于无限序列的类型,我们可以使用内置类型这里考虑的大多数算法的惰性列表。但是,为了举例说明某些观点,我将采用数学观点把序列看作是定义在自然数上的函数。下一个Haskell定义的版本将有一个内置类型自然数。目前,我将其实现为整数:

>type Natural=整数>类型Cantor=自然->位

操作员(#)需要一点时间x个和a序列并生成一个新序列x#a(x#a)具有x个作为头部和作为尾巴(很像内置操作(:)列表):

>(#)::位->康托->康托>x#a=\i->如果i==0,则x其他a(i-1)

注意,符号\i->。。。代表$\lambda i.\dots$。

接下来,我们讨论问题的核心,即执行的功能对康托空间进行穷尽搜索。的规格功能找到这是总数吗第页,其中一个应该有那个吗找到p始终是康托的全部要素空间,而且,如果有在康托空间中p a=正确,然后a=求p就是这样一个例子.

>对于某些,forevery::(Cantor->Bool)->Bool>查找::(Cantor->Bool)->Cantor

因为我将有几个找到,我必须选择一个才能编译和运行程序。A类规范选择是第一选择,

>find=find_i

但你被邀请去试验其他的。对于以下内容定义查找_i为了理解,你必须做出上述选择。

功能找到在康托上取一个谓词空格,因此它通常有一个$\lambda$-表达式参数。在以下定义中,这是不必要的,因为(a->pa)=p根据$\eta$规则。但我有为了清晰起见,我们采用了它,这样我们就可以阅读了”查找(\a->p a)“朗读为”查找这样的话第(a)页“:

>对于某些p=p(查找(\a->pa))>forevery p=not(对于某些(\a->not(pa)))

请注意,函数外汇(通用量化)从函数中获得福瑟姆(存在量化)通过德摩根法律.工作人员对某人来说查找_i由相互递归定义:

>find_i::(康托->布尔)->康托>find_i p=if for some(\a->p(零#a))>然后是零#find_i(\a->p(零#a))>else一个#find_i(\a->p(一个#a))

算法的直观思想查找(_i)清楚:如果有一个以零开始的例子,然后得出结果从零开始,否则必须从一开始。然后我们使用相同的思想递归地构建尾部。什么可能不是很明显,递归是否最终生成一个数字,因为通过调用间接递归调用对某人来说.数学证明通过归纳进行一致连续的模第页,定义如下。

只有在以下情况下才返回示例可能更自然一个,否则就说没有:

>搜索::(Cantor->Bool)->可能是Cantor>search p=如果要查找某些(\a->pa),那么只需(find(\a->pa))else Nothing

这个也许 吧类型构造函数由Haskell预定义为

data可能a=只是a |没有

类型理论备注:类型也许是一个对应于总和类型$A+1$,其中只调用$1$的元素没有什么以及在哪里只是是插入$A\toA+1美元。

练习:显示两者对某人来说找到可以是直接从定义搜索假设我们已经定义搜索第一。

常识告诉我们,函数类型没有可判定的平等。实际上,例如函数类型整数->整数由于暂停问题众所周知。然而,常识并非如此总是正确的,事实上,其他一些函数类型也有可判定的等式,例如类型康托->y对于任何类型有可判定的平等,没有反驳图灵:

>相等::方程y=>(康托尔->y)->(康托尔->y)->布尔>等于f g=forevery(a->f a==g a)

这看起来很奇怪,甚至有点可疑,因为康托空间在有些比整数大。在后续帖子中,我会解释这与Cantor空间是拓扑紧的,但整数不是。

让我们运行一个示例:

>强制::Bit->自然>强制零=0>强制一=1>f,g,h::康托->整数>f a=矫顽力>g a=胁迫(a(胁迫(a4)+11*(胁迫(a 7)))>h a=如果a 7==零>那么如果a 4==0,那么强制(a 4),否则强制(a 11)>else如果a4==One,则强制(a15)else强制(a8)

现在我们调用全球温室气体排放指数口译员:

$ghci似乎不太可能。lhs___         ___ _/ _  /  // __(_)//_///_//|GHC Interactive,6.6版,适用于Haskell 98。/ /_/ __  / /___| |      http://www.haskell.org/ghc/____///__/___/|_|类型:?寻求帮助。正在加载包基。。。正在链接。。。完成。[1 of 1]编译主目录(似乎很难理解)好的,加载的模块:主。*主菜单>

此时,我们可以在解释器的提示下计算表达式。首先,我要求它在每次评估后打印时间和空间使用情况:

*主>:集合+秒

在运行1.73GHz的Dell 410笔记本电脑上,我测试了以下内容表达:

*主>等于f gFalse(错误)(0.10秒,3490296字节)*主>等于f h真的(0.87秒,36048844字节)*主>等于g hFalse(错误)(0.09秒,3494064字节)*主>等于f f真的(0.91秒,38642544字节)*主要>等于g g真的(0.15秒,6127796字节)*主>等于h h真的(0.83秒,32787372字节)

通过改变找到,我来做这个速度更快,也可以运行更大的示例。但让我们暂时继续当前的实施。

以下是伯杰考虑上述结构:

>模数::(康托->整数)->自然>模量f=最小值(\n->forevery(a->forevely(b->eq n a b-->(f a==f b)))

这有时被称为风扇功能正常然后回到Brouwer(20世纪20年代),这在更高类型的可计算性理论中是众所周知的社区(见下文诺曼(2006))。它会找到均匀连续模,定义为最不自然编号$n$,这样

$\对于所有\alpha,\beta(\alpha=_n\beta\ to f(\alfa)=f(\beta)$

哪里

对于所有i,$\alpha=_n\beta\iff\。\alpha_i=\beta_i$

这里发生的是可计算函数是连续的,这相当于说,有限数量的输出只取决于有限数量的输入。但康托空间很紧凑在分析和拓扑学中,有一个定理说在紧空间上定义的函数是均匀地连续。在这种情况下,这相当于存在一个$n$,这样对于所有输入,只需查看深度$n$即可获得答案(在这种情况下总是有限的,因为它是一个整数)。我会在另一篇文章中解释这一切。我会的通过运行一些示例中的程序来说明这一点。

注意,Haskell定义与数学定义相同第一,只要我们定义所有其他需要的成分:

>最小值:(自然->布尔)->自然>最小p=如果p为0,则0为1+最小值(\n->p(n+1))>(-->)::布尔->布尔->布尔>p-->q=非p||q>eq::自然->康托尔->康托尔->布尔>eq 0 a b=真>eq(n+1)a b=a n==b n&&eq n a b

为了理解实际中的模量函数,定义投影如下:

>项目::自然->(康托->整数)>项目i=\a->胁迫(ai)

然后我们得到:

*主>模量(a->45000)0(0.00秒,0字节)*主要>模数(项目1)2(0.00秒,0字节)*主要>模数(项目2)(0.01秒,0字节)*主>模量(项目3)4(0.05秒,820144字节)*主要>模数(项目4)5(0.30秒,5173540字节)*主要>模数(项目5)6(1.69秒,31112400字节)*主要>模数(项目6)7(9.24秒,171456820字节)

因此,直观地说,模量是输入的最后一个指数函数使用加号。对于像上面这样的常量函数模量为零,因为没有使用指数。

技术备注.均匀模量的概念证明终止所需的连续性查找_i与上述内容不完全相同,只是略有不同(有时称为紧张的均匀模量连续性,而我们的被称为伸展的一)。但我不会去研究这样的数学这里有一些微妙之处。主要思想是,当模数为$0$时递归终止于查找_i然后开始一个新的递归生成示例的下一个数字。第页是$n+1$,谓词的模\a->p(零#a)小于等于$n$,因此总是进行递归调用模量较小,因此最终终止。的结尾备注。

现在我将尝试更快地实现找到.我将分几个阶段修改原始实现。首先,我将通过扩展函数的定义对某人来说在定义中函数查找_i:

>find_ii p=如果p(零#find_ii(\a->p(零#a)))>然后是零#find_ii(\a->p(零#a))>else一个#find_ii(\a->p(一个#a))

这应该有基本相同的速度。现在注意,如果我们使零和一成为参数小时因此,可以“考虑out”条件如下:

>find_iii::(康托尔->布尔)->康托尔>find_iii p=h#find_iid(\a->p(h#a))>其中h=如果p(Zero#find_iii(\a->p(Zero#a))),则其他为零

对于某些示例,这(以指数形式)更快。一条线索这就是那个小时只有当它是“用过”(我们的语言很懒)。让我们运行一个示例,替换上述定义找到通过find=查找iii:

*主>等于f h真的(0.00秒,522668字节)*主>相等(项目1000)真的(0.00秒,0字节)*主>相等(项目1000)(项目4000)False(错误)(0.03秒,1422680字节)*主>相等(项目1000)(项目(2^20))False(错误)(7.02秒,336290704字节)

正如你所见,我们尝试的投影函数越大,比较时间越长。要查看第一个算法有多糟糕,让我们切换回find=find_i:

*主>相等(项目10)真的(0.05秒,1529036字节)*主要>相等(项目10)(项目15)False(错误)(1.61秒,72659036字节)*主>相等(项目10)(项目20)False(错误)(60.62秒,2780497676字节)

除非我们有可用比特数超过可观测宇宙中的原子数我们愿意等待数十亿年,因为算法的连续模是指数的。

你可能注意到还有一个明显的改进从开始图dii:

>find_iv::(康托->布尔)->康托>find_iv p=let leftbranch=零#find_if(\a->p(零#a))>in if p(左分支)>然后左分支>else一个#find_iv(\a->p(一个#a))

实际上,我从来没有想过这个算法的性能或进行了试验。让我们看看我们得到了什么(您需要替换find=查找_iv):

*主>相等(项目10)(项目20)False(错误)(0.00秒,522120字节)*主>相等(项目10)(项目200)False(错误)(0.04秒,1550824字节)*主要>相等(项目10)(项目2000)False(错误)(3.71秒,146039744字节)*主要>相等(项目10)(项目20000)打断。

查找_i,但比图iii! 我在上一个例子中放弃了,因为大约一分钟后,我开始放慢这篇文章的速度。

但有一个更好的算法,我现在介绍。我不会的尝试在本文中解释此算法的工作原理(请参阅如果你真的感兴趣的话,我的LICS 2007论文如下),但我包括下面是几句话:

>find_v::(康托->布尔)->康托>find_v p=\n->如果q n(find_v(q n)),则其他为零>其中q n a=p(\i->如果i<n,则find_v p i else如果i==n,则归零else a(i-n-1))

除此之外,上述所有算法都可以很容易地重写为使用惰性列表,而不是在自然数字。此算法利用了以下事实:表示为函数的序列的元素,它不是必需的扫描前面的所有元素。这可能是一种神秘的方式算法隐式计算出其参数的条目第页使用,并且只显式构造这些。您可以访问如果你愿意的话,其他的,但是算法查找_v强制他们进行评估。有一种方法可以看出这一点查找_v是正确的就是通过归纳n个,那个findipn=findvpn,虽然计算量很大,但并不太难在某些阶段,如果不小心引入合适的辅助设备符号。更好的方法是直接理解这一点,就像在上面的文件(您需要查找产品功能概括这一点)。

现在这真的很快find=查找_v):

*主>相等(项目(2^300))(项目(2%300))真的(0.00秒,522148字节)*主>相等(项目(2^300))(项目(4^400))False(错误)(0.00秒,525064字节)

但如果函数使用了多个参数,而不仅仅是一个参数(请参见下面的示例),这不再那么好了。要解决这个问题,首先按如下所示重写上述程序,引入一个辅助程序变量b命名结果,并替换其中一个要使用的递归调用(有两个)b而是:

>find_vi::(康托->布尔)->康托>find_vi p=b>其中b=\n->如果q n(find_vi(q n)),则其他为零>q n a=p(如果i<n,则b i else如果i==n,则0 else a(i-n-1))

懒惰的评估在这里没有帮助,因为b是一个函数,实际上这会使程序稍微慢一些。现在,为了显著加快速度,我们将标识函数应用于定义b或者更确切地说是精心制作的标识函数的实现,该函数存储b以宽度第一的方式生成无限二叉树,然后将其取回(此技巧使用对数开销):

>find_vii::(康托->布尔)->康托>find_vii p=b>其中b=id’(\n->如果q n(find_vii(q n)),则归零其他1)>q n a=p(\i->如果i<n,则b i else如果i==n,则零else a(i-n-1))>数据T x=B x(T x)>代码:(天然->x)->T x>代码f=B(f 0)(代码(\n->f(2*n+1)))>(代码(\n->f(2*n+2))>解码::T x->(自然->x)>解码(B x l r)n | n==0=x>|奇数n=解码l((n-1)`div`2)>|否则=解码r((n-2)`div`2)>id’::(自然->x)->(自然->x)>id’=解码代码

现在接受find=查找_vii,并测试:

>f',g',h'::康托->整数>f'a=a'(10*a'(3^80)+100*a'>g'a=a'(10*a'(3^80)+100*a'(4^80)+1000*a'(6^80))其中a'i=胁迫(ai)>h’a=a’k>其中i=如果a'(5^80)==0,则0,否则1000>j=如果a'(3^80)==1,则10+i其他i>k=如果a'(4^80)==0,则j为100+j>a'i=矫顽力(ai)*主>等于f“g”False(错误)(6.75秒,814435692字节)*主>等于f“h”真的(3.20秒,383266912字节)*主>等于g'h'False(错误)(6.79秒,813083216字节)*主>等于f“f”真的(3.20秒,383384908字节)*主>等于g‘g’真的(3.31秒,400711084字节)*主>等于h'h'真的(3.22秒,383274252字节)

在所有上述算法中,只有发现_vii能应付用上面的例子。一个更有趣的例子是。两个自然数的有限序列$s$和$t$具有相同的设置元素的iff为两个函数

$\bigwedge_{i<|s|}\mathrm{项目}_{si}$和$\bigwedge_{i<|t|}\马特姆{项目}_{ti}$

相等,其中上面的符号表示逐点投影的逻辑和(连接),其中$|s|$是长度为$s$。下面是它的一个实现想法:

>pointwiseand::[自然]->(Cantor->Bool)>逐点和[]=\b->真>逐点与(n:a)=\b->(b n==一)&&逐点与a b>相同元素::[自然]->[自然]->布尔>相同的元素a b=相等(点和a)(点和b)*主>相同元素[6^60, 5^50, 1, 5, 6, 6, 8, 9, 3, 4, 6, 2, 4,6, 1, 6^60, 7^700, 1, 1, 1, 3, 3^30][1, 2, 3, 4, 5, 6, 7, 8, 9, 3^30, 5^50, 6^60, 7^70]False(错误)(0.14秒,21716248字节)*主>相同元素[6^60, 5^50, 1, 5, 6, 6, 8, 9, 3, 4, 6, 2, 4,6, 1, 6^60, 7^70, 1, 1, 1, 3, 3^30][1, 2, 3, 4, 5, 6, 7, 8, 9, 3^30, 5^50, 6^60, 7^70]False(错误)(0.10秒,14093520字节)*主要>相同元素[6^60, 5^50, 1, 5, 6, 6, 8, 9, 3, 4, 6, 2, 4,6, 1, 6^60, 7^70, 1, 1, 1, 3, 3^30][1, 2, 3, 4, 5, 6, 8, 9, 3^30, 5^50, 6^60, 7^70]真的(0.10秒,12610056字节)*主>相同元素[6^60, 5^50, 1, 5, 6, 6, 8, 9, 3, 4, 6, 2, 4,6, 1, 6^60, 7^70, 1, 1, 1, 3, 3^30][1, 2, 3, 4, 5, 6, 8, 9, 3^30, 5^50, 6^60, 7^700]False(错误)(0.12秒,17130684字节)*主>相同元素[6^60, 5^50, 1, 5, 6, 6, 8, 9, 3, 4, 6, 2, 4,6, 1, 6^60, 7^700, 1, 1, 1, 3, 3^30][1, 2, 3, 4, 5, 6, 8, 9, 3^30, 5^50, 6^60, 7^700]真的(0.12秒,17604776字节)

询问是否有要编程的应用程序是很自然的验证。我不知道,但是丹·吉卡我推测有,我们正计划对此进行调查。

下面的第一条评论提供了一种更快的搜索算法。


带注释的参考

  1. 乌尔里希·伯杰.Bereichtheorie中的总目标和门根.博士论文,慕尼黑LMU,1990年。
  2. M.H.埃斯卡多.允许快速穷举的无限集搜索2007年LICS,波兰,弗罗茨瓦夫,7月。下载配套Haskell程序本文研究了哪些类型的无限集允许穷举搜索。它给出了系统构建新的旧的可搜索集合。它还表明,对于丰富的类型,任何允许使用量词的子集也允许使用搜索者。这个从量词构造搜索器的算法很慢,因此,目前这一结果只具有理论意义。但是其他算法速度很快。
  3. M.H.埃斯卡多。数据类型和经典空间ENTCS,Elsevier,第87卷,第21-156页,11月2004年。我现在将此称为程序类型的算法拓扑,而不是数据类型的合成拓扑,以及在未来的写作中这就是我将要提到的。它展示了一般拓扑可以直接映射到编程语言(I再次使用Haskell)。但它也显示了如何将其映射回经典拓扑。详尽的搜索集功能如下紧集的计算表现。
  4. M.H.Escardo和W.K.Ho。操作域理论顺序编程语言的拓扑结构.2005年6月,第20届IEEE计算机科学逻辑研讨会(LICS)论文集,427-436页。如果你想了解域理论和拓扑的使用对于程序推理来说,这是一个可能的起点。而不是使用领域理论和拓扑,我们直接从的操作语义中提取它们语言(PCF,可以被视为Haskell),并列指称语义。关于领域理论和指称语义学在这里作为定理出现。那里是伯杰计划的证明,包括证明所需的一致连续模。
  5. 达格·诺曼.泛函计算——可计算性理论还是计算机科学?《符号逻辑公报》,12(1):43-592006。这是一篇关于更高类型可计算性的简短历史和调查理论(该学科是在20世纪50年代末由Kleene和Kreisel,但有一些前体)。这个理论不太好在函数式程序员中是众所周知的,但可能应该是至少在那些有理论倾向的人中。总有一天会有人应该给计算机科学家写一份解释性的报告。
  6. 亚历克斯·辛普森.精确实泛函的惰性泛函算法.英寸1998年计算机科学数学基础,Springer LNCS 1450,第456-4641998页。人们可以使用无限序列来准确地表示实数。使用通用量化函数,Alex Simpson开发了黎曼积分的一种算法。算法结果是效率低下,但这不是通用量词的错:Haskell分析器告诉我,集成程序执行关于每秒10000次通用量化,其中3000次返回真的.

评论

我发现了一种方法,通过避免使用树,而将函数视为树,可以使最快的算法速度加快约40:

>find=查找_viii>查找位::(位->布尔)->位>findBit p=如果p为零,则其他为零>分支::位->康托->康托>分支x l r n | n==0=x>|奇数n=l((n-1)`div`2)>|否则=r((n-2)`div`2)>find_viii::(康托->布尔)->康托>find_viii p=分支x l r>其中x=findBit(\x->forsome(\l->forsome(\r->p(分支x l r)))>l=find_viii(\l->用于某些(\r->p(分支x l r))>r=find_viii(\r->p(分支x l r))

这不需要记忆,因为我们需要记住的东西都绑定到where-clause中的变量。使用此算法,比较f'和g',以及f'和h'的相等性将从6.75秒和3.20秒分别移动到0.14秒和0.09秒(在所有情况下都使用格拉斯哥解释器)。

[……]事实上,这个算法并不十分有效,因为我忽略了一些细节,但它基本上是正确的。更多信息,请参阅亚历克斯·辛普森的论文,更多关于伯杰工作的信息,请参见马丁·埃斯卡德的博客文章。[...]

[…]使用Lazy Evaluation,表达式在创建后不会立即求值;相反,它被延迟,直到需要表达式的值。懒惰求值提供的一个巧妙技巧是处理无限集的能力——例如,您可以使用一个变量来保存所有自然数、所有素数或所有斐波那契数。这有时会提供相当令人惊讶的结果,例如在无限空间中进行穷尽搜索的能力。[...]

马丁,这整个帖子都很吸引人,但即使如此,最后两句话也是最有力的。我应该在哪里寻找跟进?

马丁·埃斯卡多

承诺的后续博客帖子还没有写出来,尽管在

http://math.andrej.com/2008/11/21/a-haskell-monad-for-infinite-search-in-finit-time/

然而,在我的网页上有几篇发展/应用这些想法的论文,都是在这篇文章之后写的:

  1. 高级计算中的穷举集
  2. (与P.Oliva一起)选择函数、条形递归和反向归纳。
  3. 在更高的类型设置中,可能、必须和概率测试的半决定性。
  4. 高阶方程连续解的可计算性。

几年前,马丁·埃斯卡多(Martín Escardó)写了一篇关于一个看似不可能的程序的文章,该程序可以穷尽搜索无穷大

[…]这篇文章的灵感来源于我读到的一篇有趣的文章“似乎不可能的函数程序”,这篇文章讲述了如何编写搜索无限空间的程序(我称之为[…]的元素)

说我疯了,但我打赌“你不能用Java做这件事”。

它来了:似乎不可能的Java实现了一个看似不可能的功能问题:https://github.com/untoldwind/seemingly_unpossible

好吧,我刚刚实现了前三个find,我承认这个实现是一个很容易耗尽Java堆栈的可靠方法(如果你让StackOverflow运行这个东西,你可能不得不使用-Xs512m或其他东西)。为了完整起见,我添加了自己的find-variant(FindJ),即如何在“常规Java”中解决这个小问题,不管这意味着什么(咳嗽它在<1ms内完成上述示例咳嗽).

现在,在西红柿飞起来之前:这是一次黑客攻击!这也是关于“我的语言比你的好”。函数式编程语言有其吸引力,能够以一种非常自然的方式解决某些类型的问题,Java实现是一种语法混乱。但是:我严重怀疑,有些问题只能用函数式编程语言解决。毕竟Haskell编译器无法实现魔法,尽管有时看起来可能如此。

[…]无限搜索算法,而且确实可以免费获得。这是我的博客帖子的后续内容,看起来不可能实现功能性程序。在两篇论文中,允许快速穷举搜索的无限集(LICS07)和[…]中的穷举集

[…]荷兰莱顿洛伦兹中心。我解释了如何使用计算效果来加速Martin Escardo的不可能泛函。2011年12月6日|类别:会谈,[…]

拉尔夫装载机

这些对具有状态的函数有效吗?要准确地说明想要什么,就必须注意扩展性(尽管你掩盖了它,正如你需要注意纯功能设置中的总体性一样)。

[即使上述特定程序不适用于有状态函数,Kreisel-Lacombe-Shoenfield定理也会让人认为对有状态函数也可以做同样的事情。]

@拉尔夫:这篇文章是在纯功能程序的背景下写的,即没有状态,所有功能都假定是(遗传的)总和。有了状态,事情就更复杂了(全局状态、局部状态,扩展函数使用状态意味着什么?)。

是的,正如安德烈所说,这里的一切都是扩展的和全面的,没有任何影响。但安德烈在洛伦兹中心举行的2011年MAP大会上做了一次精彩的演讲,展示了如何更快地实现效果。但在这种情况下,正如你所说,很难严格地对待外延。

拉尔夫装载机

事实证明,你可以对我的问题给出一个明智、否定的答案。find可以很容易地用monad参数化,例如[Bit和Bool合并以保存键入]。

模块MFind其中进口管制。莫纳德。findM::Ordi=>单子m=>((i->m布尔)->m布尔)->(i->m布尔)findM p n=do{x<-q(findM q);return(not x)}其中q a=p(\i->如果i==n,则返回False else如果i<n,则找到M p i else a i)--对(cx)进行虚拟调用,每次调用时x都会增加1。--然后返回(c 5)。第五个有伪::(整数->状态整数Bool)->状态整数Bool第五个有假人c=dox<-获取put(x+1)b<-c x如果b,则c 5,否则c 5--现在比较一下--找到M(5美元)0--带有--运行状态(findM(第五个带虚拟)0)0

永远不会回来。

@马丁:我说的更快的功能使用效果是在线.

[…]空间和功能秘密地连续。我之前曾在文章《看似不可能的函数程序》和《使用Haskell语言在有限时间内进行无限搜索的Haskellmonad》中利用过这一点。语言[…]

[…]在这篇看似不可能实现的函数式程序中,我编写了越来越高效的Haskell程序来实现数学[…]

安德鲁·扎巴夫尼科夫

马丁,请考虑回答以下问题:http://cs.stackexchange.com/q/45683/37997

提前感谢关注:-)

[…]看似不可能的函数程序|数学与计算http://math.andrej.com/2007/09/28/seemingly-impossible-functional-programs/ […]

[…]埃斯卡多和保罗·奥利瓦关于选择函数。对于Haskell程序员来说,好的起点是“看似不可能的函数程序”和“序列对策”、“Tychonoff定理”和“双负移”的共同点。我[…]

[…]还可以反转无限延迟数据结构上的函数。作为这种情况的特例,我们有一些看似不可能实现的功能性程序。如您所见,在某种意义上,在包含无限[…]的域上反转函数更容易

如何对此博客发表评论:目前,由于相关脚本已失效,注释被禁用。如果你在上评论这篇文章乳臭虫提到andrejbauer@mathstodon.xyz,我会的欣然回应。欢迎您加入联系我直接。