Haskell-这个素性测试中的lambda是什么意思?它是如何工作的?

Haskell-这个素性测试中的lambda是什么意思?它是如何工作的?,haskell,primes,lambda,primality-test,Haskell,Primes,Lambda,Primality Test,从中,有以下代码: isPrime n = n > 1 && foldr (\p r -> p*p > n || ((n `rem` p) /= 0 && r)) True primes 其中素数是素数的列表(可能是无限的) 两个问题: 如何读取传递给foldr函数的lambda 既然foldr是从右边开始的,那么当传递给它一个无限素数列表时,为什么这个函数可以工作呢?我猜lambda里有短路 lambda部分看起来像是被翻译成pyth

从中,有以下代码:

isPrime n = n > 1 &&
    foldr (\p r -> p*p > n || ((n `rem` p) /= 0 && r)) True primes
其中素数是素数的列表(可能是无限的)

两个问题:

  • 如何读取传递给
    foldr
    函数的lambda
  • 既然
    foldr
    是从右边开始的,那么当传递给它一个无限素数列表时,为什么这个函数可以工作呢?我猜lambda里有短路

  • lambda部分看起来像是被翻译成pythonish伪代码:

    至于
    foldr
    部分,这确实很棘手<然后,列表(
    r
    )的code>foldr)将该功能应用于头部和
    r
    。因此,必须有一个点,在这个点上,可以不进一步计算尾部


    当头部至少是
    sqrt(n)
    时就会发生这种情况,这意味着:如果有除数,你可以在之前找到它,但现在返回True,不计算尾部。

    延迟求值意味着布尔短路逻辑停止正在求值的函数链,即使逻辑在函数内部

    作为一个简单的示例,对于任何可折叠数据类型,您都可以编写如下的
    null
    函数:

    null t = foldr (\x b -> False && b) True t
    
    isPrime n = n > 1 &&
        foldr f True primes
        where
            f p r = p*p > n || ((n `rem` p) /= 0 && r)
    
    此函数永远不会被多次调用,因为对于具有多个元素的实例,它将对其求值

    False && *thunk* foldr...
    
    短路布尔值意味着thunk永远不会被计算,因此这将很好地用于无限结构。这就是为什么不应该实现
    null
    作为检查
    size==0

    这在严格的语言中不起作用;foldr的每个迭代都将依次进行评估并传递给下一个迭代

    至于lambda

    isPrime n = n > 1 &&
        foldr (\p r -> p*p > n || ((n `rem` p) /= 0 && r)) True primes
    
    可以这样写:

    null t = foldr (\x b -> False && b) True t
    
    isPrime n = n > 1 &&
        foldr f True primes
        where
            f p r = p*p > n || ((n `rem` p) /= 0 && r)
    
    希望有帮助


    编辑:如果不清楚,该函数中的短路布尔值
    |
    的工作方式与上面的简单示例相同。

    折叠可能很容易从视觉上把握:

       foldr g z [a,b,c...,x] === g a (g b (g c (g ... (g x z) ... )))
    
    因此,如果
    gpr
    不使用其第二个参数,它将不会强制任何进一步的列表访问。正如您所说,由于
    |
    (“逻辑or”)的短路行为

    foldlgz[a,b,c…,x]==(g…(g(gza)b)c)…x)

    要阅读函数,首先我们注意到折叠应用于素数列表,
    [2,3,5,7,11,13,17..]
    。所以可以理解为

    isPrime n=n>1&&
    foldr(\pr->p*p>n | |((n`rem`p)/=0&&r))真素数
    ===
    iPrime n=n>1&&
    (2*2>n | |(rem n2/=0&&
    (3*3>n | |(rem n3/=0&&
    (5*5>n||(rem n5/=0&&
    --当p*p>n时,膨胀停止
    --因为(真| | r)==真
    ......................... && 
    (对)()("""))
    

    foldr
    的组合函数中,第二个参数表示折叠列表其余部分的“结果”
    r
    是一个具有暗示意义的名称。

    你会问,“如何翻译lambda?”。我问,“翻译成什么?”thx,为澄清而编辑+对于链接,我还没有完全理解折叠的工作原理,如果p不除以n,我更喜欢
    ,返回r
    关于
    foldr
    :Haskell是懒惰的,因此实际上在第一次调用合并函数之前不会计算
    r
    。只有在请求
    r
    的值时才会尝试计算
    r
    的值。这是对折叠的一个很好的解释,但我认为我接受的答案更好地说明了折叠和lambda在这种情况下是如何工作的。嗯,我开始说这是关于短路布尔逻辑,在LAMBDA的中间有一个大的<代码> <代码>代码SLAP。在你更新之前,根本不清楚你所说的“lambda是如何工作的?”。我接受了这个答案,因为它更清楚地解释了折叠和lamdba在这个函数中是如何工作的。谢谢