在SML中使用fold

时间:2012-03-09 04:28:30

标签: functional-programming sml smlnj

我正在尝试学习smlnj,并且遇到折叠功能问题。

我要做的是编写一个函数,选择,使用折叠模式并接受函数和列表。它将使列表的头部进入函数以确定它是否将该元素添加到列表中。这是我的意思的一个例子。

          select (fn x => x mod 2 = 0) [1,2,3,4,5,6,7,8,9,10];
          val it = [2,4,6,8,10] : int list

所以,这就是我到目前为止......

          fun select f l = foldl (fn (x,y) => if (f(x)) then x else 0) 0 l;

这显然无法正常工作。它只返回10.我确信我需要使用op :: somehow来使其工作,但我无法弄明白。我的想法是它应该看起来像这样......

          fun select f l = foldl (fn (x,y) => if (f(x)) then op:: else []) [] l;

但这不起作用。任何帮助,将不胜感激。谢谢!

2 个答案:

答案 0 :(得分:4)

你很亲密。唯一的问题是您传递给if的函数中的else / fold个案例。

请记住,在您的fn (x,y)中,x是您正在考虑的列表元素,y是折叠列表其余部分的结果。如果f(x)失败,则您希望从结果中排除x,因此您只需传递y。如果f(x)成功,您希望在结果中加入x,以便返回y@[x]

请注意,最好避免使用追加运算符(y@[x]),因为它是线性时间操作,而前置(x::y)是常量。当然,在这种情况下用一个代替另一个将向后构建你的列表。您也可以通过向后折叠来解决这个问题,即使用foldr代替foldl

答案 1 :(得分:2)

您正在实施的内容已经存在。它被称为filter

- List.filter (fn x => x mod 2 = 0) [1,2,3,4,5,6,7,8,9,10];
val it = [2,4,6,8,10] : int list

您在第二个代码示例中的尝试非常接近。我可能会指出几个问题:

  • op::是一个运算符,它是一个函数。您可能不想返回一个函数。相反,您可能希望使用运算符从head元素和列表的其余部分创建列表,如下所示:x :: y

  • 在else的情况下,您当前正在返回一个空列表,并丢弃y中累积的内容。你可能不想这样做。

  • 考虑左折或右折是否最适合您的输出