返回SML中的偶数列表

返回SML中的偶数列表,sml,Sml,我一直在学习SML,这已经证明是一项相当艰巨的任务。我试图创建一个函数,它接受一个整数列表,然后只返回该列表中的偶数 以下是我到目前为止的情况: fun isEven [] = [] | val evenList if x mod 2 = 1 then //append to evenList 我对下一步该做的事感到非常困惑。有人能解释一下吗?在本例中(以及对于大多数列表处理问题),通常最容易从考虑两种可能性开始:列表是空的,或者不是空的。当列表为空时,

我一直在学习SML,这已经证明是一项相当艰巨的任务。我试图创建一个函数,它接受一个整数列表,然后只返回该列表中的偶数

以下是我到目前为止的情况:

fun isEven [] = [] |
    val evenList            
    if x mod 2 = 1 then //append to evenList
我对下一步该做的事感到非常困惑。有人能解释一下吗?

在本例中(以及对于大多数列表处理问题),通常最容易从考虑两种可能性开始:列表是空的,或者不是空的。当列表为空时,问题可能很难解决。当列表不为空时,可以将列表分解为两部分:第一个元素(“head”),其余元素(“tail”)

在代码中,我们可以根据输入的外观编写许多不同版本的函数。下面我将对输入进行模式匹配,并根据输入是否为空编写两个不同的函数体。当它不为空时,列表的头部绑定到变量
x
,尾部绑定到变量
xs

fun f []        = (* ... empty case ... *)
  | f (x :: xs) = (* ... non-empty case ... *)
在这种“惯用”方法下,您可以问:当列表非空时,如何递归地解决问题?也就是说,是否可以对列表的尾部应用相同的函数,并使用该函数构造最终答案

fun f []        = (* ... TODO: trivial when list is empty ... *)
  | f (x :: xs) =
      let
        val foo = f xs
      in
        (* ... TODO: how to use `foo`? ... *)
      end

在这一点上,我将把其余的留给你。试着填补空白:
foo
在你的问题中代表了什么?您需要如何处理head元素
x

一个名为
isEven
的函数听起来像一个谓词,而不是一个过滤器

fun isEven n =
    n mod 2 = 0
你可以称之为evens:

fun evens [] = ... (* base case *)
  | evens (n::ns) = ... (* recursive case *)
现在,您可以调用
isEven
,以确定
n::ns
的第一个
n
(至少有一个,否则函数将匹配基本情况而不是递归情况)是否为偶数:

注意,SML中的if-then-else必须有一个else部分

在这两种情况下,您都希望在
ns
上继续查找evens,但您只希望根据
isEven n
的值在结果中包含
n
。您可以通过创建一个新列表,在该列表中
n
也是一个成员,从而在结果中包含一些内容。例如,将列表中的每个元素递增1的函数:

fun incr [] = []
  | incr (n::ns) = n+1 :: incr ns
除了在
evens
的情况下,您不想修改
n
,并且
n:…
部分是有条件的。

List.filter(fn i=>i mod 2=0)
fun incr [] = []
  | incr (n::ns) = n+1 :: incr ns