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 根据标准ML中的foldr定义foldl_Haskell_Functional Programming_Sml_Fold - Fatal编程技术网

Haskell 根据标准ML中的foldr定义foldl

Haskell 根据标准ML中的foldr定义foldl,haskell,functional-programming,sml,fold,Haskell,Functional Programming,Sml,Fold,定义的代码是 fun foldl f e l = let fun g(x, f'') = fn y => f''(f(x, y)) in foldr g (fn x => x) l e end 我不明白这是怎么回事; g(x,f')的目的是什么 我在Haskell也发现了一个类似的例子, 定义很短 myFoldl f z xs = foldr step id xs z where step x g a = g (f a x) 让我们分析一

定义的代码是

fun foldl f e l = let
    fun g(x, f'') = fn y => f''(f(x, y)) 
    in foldr g (fn x => x) l e end
我不明白这是怎么回事;
g(x,f')
的目的是什么

我在Haskell也发现了一个类似的例子, 定义很短

myFoldl f z xs = foldr step id xs z
    where
        step x g a = g (f a x)

让我们分析一下
myFoldl
的Haskell实现,然后看看ocamlsml代码。首先,我们将了解一些类型签名:

foldr::(a->b->b)--步进函数
->b——累加器的初始值
->[a]——要折叠的列表
->b--结果如何
应该注意的是,尽管
foldr
函数只接受三个参数,但我们应用了两个或四个参数:

foldr步骤id xs z
但是,正如您所看到的,
foldr
(即累加器的初始值)的第二个参数是
id
,它是
x->x
类型的函数。因此,结果也是
x->x
类型。因此,它接受四个论点

类似地,step函数现在是
a->(x->x)->x->x
类型。因此,它接受三个参数,而不是两个参数。累加器是一个函数(即域和辅域相同的函数)

内函数有一个特殊的性质,它们是从左到右而不是从右到左组成的。例如,让我们组合一组
Int->Int
函数:

inc::Int->Int
inc n=n+1
dbl::Int->Int
DBLn=n*2
合成这些函数的常规方法是使用函数合成运算符,如下所示:

incDbl::Int->Int
incDbl=inc。dbl
incDbl
函数首先将数字加倍,然后递增。请注意,这是从右向左读取的

组成它们的另一种方法是使用连续体(由
k
表示):

inc':(Int->Int)->Int->Int
inc'kn=k(n+1)
dbl':(Int->Int)->Int->Int
dbl'kn=k(n*2)
请注意,第一个参数是一个延续。如果我们想恢复原始功能,我们可以:

inc::Int->Int
inc=inc'id
dbl::Int->Int
dbl=dbl'id
但是,如果我们想编写它们,那么我们将按如下方式进行:

incDbl':(Int->Int)->Int->Int
incDbl'=dbl'。公司
incDbl::Int->Int
incDbl=incDbl'id
请注意,尽管我们仍然使用点运算符来编写函数,但它现在从左向右读取

这是使
foldr
表现为
foldl
的关键。我们将列表从右向左折叠,但不是将其折叠成一个值,而是将其折叠成一个内函数,当应用于初始累加器值时,它实际上将列表从左向右折叠

考虑我们的
incDbl
功能:

incDbl=incDbl'id
=(dbl'.inc')id
=dbl'(inc'id)

现在考虑<代码> FordR < /代码>:

foldr::(a->b->b)->b->[a]->b
foldr_uuACC[]=acc
foldr fun acc(y:ys)=fun y(foldr fun acc ys)
在基本情况下,我们只返回累积值。然而,在归纳的情况下,我们返回
funy(foldr-fun-acc-ys)
。我们的
步骤
功能定义如下:

step::a->(x->x)->x->x
步骤x g a=g(f a x)
这里的
f
foldl
的减速器函数,类型为
x->a->x
。请注意,
步骤x
(x->x)->x->x
类型的内函数,我们知道它可以从左到右组合

因此,列表
[y1,y2..yn]
上的折叠操作(即
折叠步骤id
)如下所示:

步骤y1(步骤y2(…(步骤yn id)))
--或
(步骤y1.步骤y2.{dots}.步骤yn)id
每个
步骤yx
都是一个内函数。因此,这相当于从左到右组合内函数

当此结果应用于初始累加器值时,列表将从左向右折叠。因此,
myFoldl f z xs=foldr步骤id xs z


现在考虑<代码> FooLDL/COD>函数(用标准ML编写,而不是OCAML)。其定义如下:

fun foldl f e l=让fun g(x,f'')=fn y=>f''(f(x,y))
在foldr g(fn x=>x)l e end中
Haskell和SML的
foldr
函数之间的最大区别是:

  • 在Haskell中,reducer函数的类型为
    a->b->b
  • 在SML中,减速器功能的类型为
    (a,b)->b
  • 两者都是正确的。这只是偏好的问题。在SML中,不是传递两个单独的参数,而是传递一个包含两个参数的元组

    现在,相似之处是:

  • Haskell中的
    id
    函数是SML中的匿名
    fn x=>x
    函数
  • Haskell中的
    step
    函数是SML中的
    g
    函数,它接受包含前两个参数的元组
  • step
    函数是Haskell
    step x g a
    在SML
    g(x,f'')=fn y=>f''(f(x,y))
    中被分成两个函数,以更清楚地说明问题
  • 如果我们重写SML函数以使用与Haskell中相同的名称,那么我们有:

    fun myFoldl f z xs=let step(x,g)=fn a=>g(f(a,x))
    在foldr步骤中(fn x=>x)xs z结束
    
    因此,它们是完全相同的函数。表达式
    g(x,f')
    只是将函数
    g
    应用于元组
    (x,f')
    。这里的
    f'
    是一个有效的标识符。

    foldl函数在使用累加器操作元素时从头到尾遍历列表:

    (……(a)⊗x1)⊗...⊗xn-1)⊗xn

    您想通过foldr定义它:

    x1⊕(x2⊕...⊕(xn⊕e) …)

    <
       foldr ⊕ [1,2,3] id 
    -> 1⊕(2⊕(3⊕id))
    -> 1⊕(2⊕(id.(+3))
    -> 1⊕(id.(+3).(+2))
    -> (id.(+3).(+2).(+1))
    
       (id.(+3).(+2).(+1)) 0
    =  ((0+1)+2)+3
    
    n ⊕ g = g . (+n)   
    
    foldl (+) 0 xs = foldr ⊕ id xs 0 
                   where n ⊕ g = g . (+n)   
    
    foldl (+) 0 xs = foldr ⊕ id xs 0
                   where (⊕) n g a = g (a+n)   
    
    h []     = e
    h (x:xs) = f x (h xs)
    
          iff 
    
    h = foldr f e
    
    h xs a = foldl f a xs
    
    h xs = \a -> foldl f a xs
    
    h [] = \a -> foldl f a []
         = \a -> a
         = id
    
    h (x:xs) = \a -> foldl f a (x:xs)
             = \a -> foldl f (f a x) xs
             = \a -> h xs (f a x)
             = step x (h xs)   where step x g = \a -> g (f a x) 
             = step x (h xs)   where step x g a = g (f a x) 
    
    h []     = id
    h (x:xs) = step x (h xs) where step x g a = g (f a x) 
    
    h      = foldr step id
    h xs a = foldl f a xs
    -----------------------
    foldl f a xs = foldr step id xs a  
                 where step x g a = g (f a x)