猿问

解释这段输出素数流的haskell代码

解释这段输出素数流的haskell代码

我很难理解这段代码:

let
  sieve (p:xs) = p : sieve (filter (\ x -> x `mod` p /= 0) xs)in sieve [2 .. ]

有人可以为我分解吗?我知道其中存在递归,但这就是我无法理解此示例中的递归如何工作的问题。


慕雪6442864
浏览 690回答 3
3回答

芜湖不芜

它定义了一个生成器-&nbsp;一个称为“ sieve”的流转换器,Sieve&nbsp;s&nbsp;=&nbsp; &nbsp;&nbsp;while(&nbsp;True&nbsp;): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;:=&nbsp;s.head &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;:=&nbsp;s.tail &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield&nbsp;p&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&nbsp;produce&nbsp;this &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;:=&nbsp;Filter&nbsp;(nomultsof&nbsp;p)&nbsp;s&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&nbsp;go&nbsp;nextprimes&nbsp;:=&nbsp;Sieve&nbsp;(Nums&nbsp;2)它使用等效于匿名函数的咖喱形式nomultsof&nbsp;p&nbsp;x&nbsp;=&nbsp;(mod&nbsp;x&nbsp;p)&nbsp;/=&nbsp;0两个Sieve和Filter是数据构造与操作的内部状态和通过值参数传递语义。在这里,我们可以看到,最突出的问题这段代码是不是,重复不在于它使用审判庭从工作序列筛选出数倍,而它可以直接将它们找出来,通过在增量计数p。如果我们要用后者代替前者,那么生成的代码将仍然具有极高的运行时复杂性。不,它最明显的问题是它过早地将其Filter放在工作序列的顶部,只有在输入中看到素数平方之后才真正应该这样做。结果,与实际需要的相比,它创建了s&nbsp;的二次数。它创建的s&nbsp;链太长,甚至根本不需要它们中的大多数。FilterFilter过滤器的创建被推迟到适当的时候的更正版本是Sieve&nbsp;ps&nbsp;s&nbsp;=&nbsp; &nbsp;&nbsp;while(&nbsp;True&nbsp;): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;:=&nbsp;s.head &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;:=&nbsp;s.tail &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield&nbsp;x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&nbsp;produce&nbsp;this &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;:=&nbsp;ps.head &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q&nbsp;:=&nbsp;p*p &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(&nbsp;(s.head)&nbsp;<&nbsp;q&nbsp;): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield&nbsp;(s.head)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;these &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;:=&nbsp;s.tail &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ps&nbsp;:=&nbsp;ps.tail&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&nbsp;go&nbsp;next &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;&nbsp;:=&nbsp;Filter&nbsp;(nomultsof&nbsp;p)&nbsp;s primes&nbsp;:=&nbsp;Sieve&nbsp;primes&nbsp;(Nums&nbsp;2)或在Haskell中,primes&nbsp;=&nbsp;sieve&nbsp;primes&nbsp;[2..]&nbsp;sieve&nbsp;ps&nbsp;(x:xs)&nbsp;=&nbsp;x&nbsp;:&nbsp;h&nbsp;++&nbsp;sieve&nbsp;pt&nbsp;[x&nbsp;|&nbsp;x&nbsp;<-&nbsp;t,&nbsp;rem&nbsp;x&nbsp;p&nbsp;/=&nbsp;0] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where&nbsp;(p:pt)&nbsp;=&nbsp;ps&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(h,t)&nbsp;&nbsp;=&nbsp;span&nbsp;(<&nbsp;p*p)&nbsp;xsrem此处使用而不是,mod因为在某些口译员中它可以更快,并且无论如何这些数字都是正数。通过以问题大小点的运行时间来衡量算法的局部增长阶次,如,我们得到第一个,而第二个正好在上面(以产生的素数计)。t1,t2n1,n2logBase (n2/n1) (t2/t1)O(n^2)O(n^1.4)n只是为了澄清一下,可以用这种(虚构的)语言定义缺少的部分,就像Nums&nbsp;x&nbsp;=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&nbsp;numbers&nbsp;from&nbsp;x &nbsp;&nbsp;while(&nbsp;True&nbsp;): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield&nbsp;x &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;:=&nbsp;x+1Filter&nbsp;pred&nbsp;s&nbsp;=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&nbsp;filter&nbsp;a&nbsp;stream&nbsp;by&nbsp;a&nbsp;predicate &nbsp;&nbsp;while(&nbsp;True&nbsp;): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;pred&nbsp;(s.head)&nbsp;then&nbsp;yield&nbsp;(s.head) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;:=&nbsp;s.tail另见。更新:奇怪的是,根据AJT Davie在1992年Haskell的书中,David Turner的1976 SASL手册中的第一个代码实例,&nbsp;&nbsp;&nbsp;&nbsp;primes&nbsp;=&nbsp;sieve&nbsp;[2..] &nbsp;&nbsp;&nbsp;&nbsp;sieve&nbsp;(p:nos)&nbsp;=&nbsp;p&nbsp;:&nbsp;sieve&nbsp;(remove&nbsp;(multsof&nbsp;p)&nbsp;nos)实际上接受并实现了两&nbsp;对实现-一对用于此问题的试验部门筛网,另一对用于通过计算直接减去每个素数的倍数(也就是真正的Eratosthenes筛子)的有序去除(两者都是当然不推迟)。在Haskell,removemultsof&nbsp;&nbsp;&nbsp;&nbsp;multsof&nbsp;p&nbsp;n&nbsp;=&nbsp;rem&nbsp;n&nbsp;p==0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remove&nbsp;m&nbsp;xs&nbsp;=&nbsp;filter&nbsp;(not&nbsp;.&nbsp;m)&nbsp;xs &nbsp;&nbsp;&nbsp;&nbsp;multsof&nbsp;p&nbsp;=&nbsp;[p*p,&nbsp;p*p+p..]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remove&nbsp;m&nbsp;xs&nbsp;=&nbsp;diff&nbsp;xs&nbsp;m(如果他只是推迟选择实际的实现方式...)至于推迟的代码,在带有“列表模式”&nbsp;的伪代码中,&nbsp;&nbsp;&nbsp;&nbsp;primes&nbsp;=&nbsp;[2,&nbsp;...sieve&nbsp;primes&nbsp;[3..]] &nbsp;&nbsp;&nbsp;&nbsp;sieve&nbsp;[p,&nbsp;...ps]&nbsp;[...h,&nbsp;p*p,&nbsp;...nos]&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[...h,&nbsp;...sieve&nbsp;ps&nbsp;(remove&nbsp;(multsof&nbsp;p)&nbsp;nos)]
随时随地看视频慕课网APP
我要回答