【问题标题】:Using ListPair.foldr to implement zipWith in SMLSML中使用ListPair.foldr实现zipWith
【发布时间】:2013-01-11 03:27:04
【问题描述】:

背景:SML 初级水平

我的任务要求我使用 ListPair.foldr 并且只有这个函数来实现 zipWith 函数。

ListPair.foldr : ('a * 'b * 'c -> 'c) -> 'c -> 'a list * 'b list -> 'c
zipWith : ('a * 'b -> 'c) -> 'a list -> 'b list -> 'c list

ListPair.foldr 返回单个 'c 元素,而 zipWith 返回一个 'c 列表,所以我的方法自然会反复使用 ListPair.foldr 来溢出单个 'c 元素,然后我将其放入我的 'c 列表中。 ListPair.foldr 采用一对列表并根据提供的函数将它们相互折叠,因此获得所需效果的唯一方法是一次从每个列表中获取一个元素,将其作为 ListPair.foldr一对列表,获取结果,并将其连接到下一轮。 我还必须将函数从 ('a*'b->'c) 转换为 ('a*'b*'c->'c)。 像这样:

fun zipWith f [] l2 = []
| zipWith f l1 l2 = 
let val f2 = fn (a,b,c)=> f(a,b)+c   (* converting the function *)
    val xh = [hd(l1)]      (*first element of 'a list, as a list itself *)
    val yh = [hd(l2)]      (*first element of 'b list, as a list itself *)
    val xt = tl(l1)        (*taking the tail of 'a list*)
    val yt = tl(l2)        (*taking the tail of 'b list*)
in
    ListPair.foldr f2 0 (xh, yh)::    (*perform the operation with the two heads*)
    zipWith f xt yt                   (*recursively call zipWith with the remainder*)
end;

这行得通。

- zipWith (fn (x,y)=>x+y) [1,2,3] [10,20,30];
val it = [11,22,33] : int list

但现在棘手的部分是:我不应该递归地执行此操作,也就是说,我不能在我的 zipWith 函数中调用 zipWith。 这甚至可能吗?根据我的阅读,Haskell 中的实际 zi​​pWith 函数是递归定义的;我如何以非递归方式执行此操作?

我无法想象教授会敦促我们以面向对象的方式使用 while 循环之类的方式来做这件事(无论如何我都试过了,我的水平还不够)。

我是不是走错了方向?我应该如何处理这个问题?

-----------------已回答----------------

其实我一开始也试过pad的方案:

fun zipWith f l1 l2 = 
let val f2 = fn (a,b,c)=> f(a,b)::c
in
    ListPair.foldr f2 0 l1 l2
end;

但它不起作用,因为我将它附加到 0 而不是 []。类型不成立,我想不通!

谢谢!

【问题讨论】:

    标签: list functional-programming sml currying


    【解决方案1】:

    您的方法是正确的,但不必要地复杂。函数zipWith 是递归的,但您可以非递归地定义它,因为ListPair.foldr 已经具有递归性质。

    要更接近zipWith,您需要具有以下签名的ListPair.foldr 的专用版本

    ListPair.foldr : 
       ('a * 'b * 'c list -> 'c list) -> 'c list -> 'a list * 'b list -> 'c list
    

    这意味着您将一个空列表作为累加器传递,并在此过程中建立更大的列表。在zipWith f xs ysf'a * 'b -> 'c签名,所以很容易适配:

    fun zipWith f xs ys =
        ListPair.foldr (fn (a, b, cs) => f(a, b)::cs) [] (xs, ys)
    

    【讨论】:

    • 谢谢,太好了!我发现了我的问题:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    • 2019-11-03
    • 2014-03-23
    • 2018-03-30
    • 1970-01-01
    相关资源
    最近更新 更多