Functional programming 从sml中的整数对列表返回偶数列表

Functional programming 从sml中的整数对列表返回偶数列表,functional-programming,sml,smlnj,Functional Programming,Sml,Smlnj,我有一个问题:“给定一个整数对列表,编写一个函数以在sml中返回该列表中的偶数列表” 这就是我到目前为止所取得的成就 val x = [(6, 2), (3, 4), (5, 6), (7, 8), (9, 10)]; fun isEven(num : int) = if num mod 2 = 0 then num else 0; fun evenNumbers(list : (int * int) list) = if null list then [] else

我有一个问题:“给定一个整数对列表,编写一个函数以在sml中返回该列表中的偶数列表”

这就是我到目前为止所取得的成就

val x = [(6, 2), (3, 4), (5, 6), (7, 8), (9, 10)];

fun isEven(num : int) = 
    if num mod 2 = 0 then num else 0;

fun evenNumbers(list : (int * int) list) = 
    if null list then [] else 
    if isEven(#1 (hd list)) <> 0
    then if isEven(#2 (hd list)) <> 0
         then #1 (hd list) :: #1 (hd list) :: evenNumbers(tl list)
         else []
    else if isEven(#2 (hd list)) <> 0
         then #1 (hd list) :: evenNumbers(tl list)
         else [];

evenNumbers(x);
valx=[(6,2)、(3,4)、(5,6)、(7,8)、(9,10)];
乐趣无穷(num:int)=
如果num mod 2=0,则num else为0;
有趣的数字(列表:(int*int)列表)=
如果列表为空,则为[]else
如果isEven(#1(hd列表))0
那么如果isEven(#2(hd list))0
然后#1(高清列表)::#1(高清列表)::偶数(tl列表)
其他[]
否则如果isEven(#2(hd列表))0
然后#1(hd列表)::偶数(tl列表)
else[];
偶数(x);
结果应该是这样的
[6,2,4,6,8,10]


任何帮助都将不胜感激。

因此,运行您当前的代码

- evenNumbers [(6, 2), (3, 4), (5, 6), (7, 8), (9, 10)];
val it = [6,6,3,5,7,9] : int list
这表明您并没有捕获所有偶数,而是捕获了一些奇数

函数
isEven
听起来很像您想要的类型
int->bool
,如下所示:

fun isEven n =
    n mod 2 = 0

与其解决当前解决方案的逻辑错误,我想提出一种语法上更简单的方法,即使用模式匹配和更少的显式类型注释。这种解决方案的一个基础可能是:

fun evenNumbers [] = ...
  | evenNumbers ((x,y)::pairs) = ...
使用模式匹配是if-then-else的一种替代方法:
[]
模式相当于
if-null列表…
(x,y)::当输入列表为非空(包含至少一个元素,即
(x,y))时成对的
模式匹配
。同时,它将这一元素解构为其各个部分,
x
y
。因此,在第二个函数体中,您可以表示
isEven x
isEven y

由于总共有四种组合决定了
x
y
是否为偶数,因此很容易就会产生类似复杂的if-then-else。为此,我可以做两件事中的一件:

  • 用例(并在
    对上递归调用
    偶数
    ):

  • 将对列表展平为整数列表,然后:


  • 我看到两个明显的问题

    如果第一个数字和第二个数字都是偶数,则为偶数

    #1 (hd list) :: #1 (hd list) :: evenNumbers(tl list)
    
    #1 (hd list) :: evenNumbers(tl list)
    
    它将第一个数字相加两次并忽略第二个数字

    如果第一个数字是奇数,第二个数字是偶数,你就可以

    #1 (hd list) :: #1 (hd list) :: evenNumbers(tl list)
    
    #1 (hd list) :: evenNumbers(tl list)
    
    它将你知道的奇数相加,而忽略你知道的偶数

    使用选择器和条件的编程很快就会变得复杂(正如您所注意到的)

    通过模式匹配,您可以编写

    fun evenNumbers [] = []
      | evenNumber ((x,y)::xys) = ...
    
    并降低使用错误选择器的风险

    然而,这仍然会导致复杂的逻辑,还有更好的方法

    考虑一个更简单的问题,即从数字列表中筛选奇数,而不是成对的数字。
    如果您将输入转换为这样一个列表,您只需要解决这个简单的问题(在前面的练习中,您很可能已经解决了一些非常类似的问题)

    练习:实现此转换。其类型将是
    ('a*'a)list->'a list

    此外,如果你的
    isEven
    产生一个真值(如果你问某人,“36是偶数吗?”,“36”是一个非常奇怪的答案),那么它会更有用

    现在,
    evernumbers
    可以“仅仅”实现为其他更通用功能的组合

    fun isEven x = x mod 2 = 0