Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 解释如何使用foldl的此特定功能_Haskell - Fatal编程技术网

Haskell 解释如何使用foldl的此特定功能

Haskell 解释如何使用foldl的此特定功能,haskell,Haskell,foldl是从左侧向上折叠列表。因此,首先我们得到acc=0并将列表xs放到x,然后执行函数->acc+x。经过计算,我们得到新的acc,它等于acc+x。但为什么呢?我认为acc+x的这个结果是基于函数x->acc+x的x的新值。你应该看看foldl的定义: sum :: (Num a) => [a] -> a sum xs = foldl (\acc x -> acc + x) 0 xs foldl接收一个函数,该函数包含两个参数、一个值(“起始值”或累加器)

foldl是从左侧向上折叠列表。因此,首先我们得到
acc=0
并将列表xs放到x,然后执行函数
->acc+x
。经过计算,我们得到新的acc,它等于
acc+x
。但为什么呢?我认为
acc+x
的这个结果是基于函数
x->acc+x
的x的新值。你应该看看foldl的定义:

 sum :: (Num a) => [a] -> a  
 sum xs = foldl (\acc x -> acc + x) 0 xs  
foldl接收一个函数,该函数包含两个参数、一个值(“起始值”或累加器)和一个列表。 如果列表为空,则返回当前计算。 如果大小写不为空,则它使用与函数相同的函数递归调用,累加器是函数调用的结果,使用累加器作为第一个参数,列表的第一个元素作为第二个参数,列表的尾部用作递归调用的列表

因此,sum中使用的lambda函数变得非常清楚,它将acc作为第一个参数,将列表的元素作为第二个参数,并返回两者的和

调用以下各项的结果:

foldl  f z []     =  z
foldl  f z (x:xs) =  foldl f (f z x) xs

您应该看看foldl的定义:

 sum :: (Num a) => [a] -> a  
 sum xs = foldl (\acc x -> acc + x) 0 xs  
foldl接收一个函数,该函数包含两个参数、一个值(“起始值”或累加器)和一个列表。 如果列表为空,则返回当前计算。 如果大小写不为空,则它使用与函数相同的函数递归调用,累加器是函数调用的结果,使用累加器作为第一个参数,列表的第一个元素作为第二个参数,列表的尾部用作递归调用的列表

因此,sum中使用的lambda函数变得非常清楚,它将acc作为第一个参数,将列表的元素作为第二个参数,并返回两者的和

调用以下各项的结果:

foldl  f z []     =  z
foldl  f z (x:xs) =  foldl f (f z x) xs

从您的问题来看,听起来您不明白lambda函数
(\acc x->acc+x)
在这里是如何工作的

该功能不是
x->acc+x
,而是
acc x->acc+x
。事实上,你可以把“和”方程改写为

sum [1,2,3] = ((0 + 1) + 2) + 3 = 6
因为
(\acc x->acc+x)
(+)


我建议您(重新)阅读您的问题,听起来您不明白lambda函数
(\acc x->acc+x)
在这里是如何工作的

该功能不是
x->acc+x
,而是
acc x->acc+x
。事实上,你可以把“和”方程改写为

sum [1,2,3] = ((0 + 1) + 2) + 3 = 6
因为
(\acc x->acc+x)
(+)


我建议你(重读)

让我们看看你对总和的定义

sum xs = foldl (+) 0 xs
让我们也来看看foldl的签名:

sum :: (Num a) => [a] -> a  
sum xs = foldl (\acc x -> acc + x) 0 xs  
嗯,好的,我们需要向foldl输入什么才能得到最末端的值(
->a

  • 它需要一个通用函数
    (a->b->a)
    。虽然不准确,但为了简洁起见,我们会说它是一个接受两个参数的函数(但你我都知道,它接受一个参数并返回另一个接受一个参数的函数)

  • 它需要类型为
    a
    的值。请注意,我们的curried函数来自步骤1。获取
    a
    类型的内容并返回
    a
    类型的内容。有趣…嗯

  • 它需要类型为
    b
    的列表。注意我们在步骤1中使用的curry函数,以及
    a
    类型和
    b
    类型的函数

  • 那么,我们能给它想要的吗

  • 我们给它
    (\acc x->acc+x)
    。这是一个匿名函数,或lambda,它接受两个参数(记住,它是用咖喱做成的),
    acc
    x
    ,并返回它们的和

  • 我们将其
    0
    作为起始值

  • 我们给它
    xs
    作为折叠列表

  • 好的,多奇。那么,让我们让foldl发挥它的Haskell魔力吧。让我们想象一下,我们称之为
    sum[1,2,3]

    foldl
    调用我们的函数
    (\acc x->acc+x)
    ,为
    acc
    使用
    0
    xs
    的第一个值,
    1

    foldl :: (a -> b -> a) -> a -> [b] -> a
    
    这个结果不会存储在
    acc
    x
    中,因为它们只是我们的小lambda函数中的参数
    foldl
    将使用该值(有关具体实现,请参阅的答案)

    记住,lambda函数的结果与第一个参数的类型相同吗?foldl可以使用前一个和,并将其与second元素一起传递回lambda函数

     0 + 1
    
    在对所有元素执行此操作之前:

    (0 + 1) + 2
    
    正如所指出的,如果您已经执行了以下操作,这是相同的:

    ((0 + 1) + 2) + 3
    6
    
    使用此函数,您可以更容易地看出,我们不仅仅是“设置”某个变量并将其添加到其中

    希望这有帮助


    旁注: 对于sum的定义,您不必明确说明
    sum
    采用
    xs
    。您可以将其保留为:

    sum=foldl(\acc x->acc+x)0

    这就利用了curry,因为如果我们只提供foldl的前两个参数——像
    (a->b->a)
    这样的curry函数和
    a
    类型的值——我们会得到什么

    [b]->a


    一种函数,它接受类型为
    b
    的列表,并返回类型为
    A
    的值!这就是所谓的。只是考虑一下:-(<

    >P>)让我们看一下你的和的定义< /P>

    sum xs = foldl (+) 0 xs
    
    让我们也来看看foldl的签名:

    sum :: (Num a) => [a] -> a  
    sum xs = foldl (\acc x -> acc + x) 0 xs  
    
    嗯,好的,我们需要向foldl输入什么才能得到最末端的值(
    ->a

  • 它需要一个通用函数
    (a->b->a)
    。虽然不准确,但为了简洁起见,我们会说它是一个包含两个参数的函数(但你我都知道