Sml 在新泽西州创建交叉点和差异点

Sml 在新泽西州创建交叉点和差异点,sml,smlnj,ml,Sml,Smlnj,Ml,使用前面构造的函数contains,编写一个函数intersection,它接受两个列表(建模集),并返回两个集合的交集的列表。所以 intersection([1, 2, 3], [1, 3]) 将返回[1,3] 使用前面构造的函数contains,编写一个函数difference,它获取两个列表,并返回一个列表,模拟第一个集合与第二个集合的差异(集合a–集合B) 我已经创建了下面的代码contains,现在我的目标是创建一个交叉点和差异函数 fun contains(x, []) = fa

使用前面构造的函数
contains
,编写一个函数
intersection
,它接受两个列表(建模集),并返回两个集合的交集的列表。所以

intersection([1, 2, 3], [1, 3])
将返回
[1,3]

使用前面构造的函数
contains
,编写一个函数
difference
,它获取两个列表,并返回一个列表,模拟第一个集合与第二个集合的差异(集合a–集合B)

我已经创建了下面的代码
contains
,现在我的目标是创建一个
交叉点
差异
函数

fun contains(x, []) = false
  | contains(x, y::rest) = 
    if x = y
    then true 
    else contains(x, rest);

fun intersection([], y) = []
  | intersection(x, y) = if x = y
   then [x,y]
   else [];;
试一试:

- intersection([1, 2], [2, 3]);
val it = [] : int list list

对于您的
包含的
功能,可以稍加改进:

fun contains(x, []) = false
  | contains(x, y::rest) = 
    x = y orelse contains(x, rest)
也就是说,
如果p为真,则else Q
p或else Q
相同

高阶标准库解决方案是编写

fun contains (x, ys) = List.exists (fn y => x = y) ys
但如果练习是为了证明对基本递归的理解,则前者更可取

至于您的
交集
函数,似乎无论您如何设法使
包含
,您都没有应用相同的列表递归原则。您可以比较
x=y
,但这里
x
y
是列表,而不是单个元素。而在
contains
中,
x
是列表/集合中的单个值,
y
是列表/集合的第一个元素
y::rest

因此,您可能应该开始用一个类型注释每个参数,或者以这样一种方式命名它,这样您就不会怀疑它应该表示什么。对于
intersection
,规则是您只需要作为两个列表/集合的成员的元素

例如:

fun intersection (xs, ys) = ...
或带有注释的类型:

fun intersection (xs : ''a list, ys : ''a list) = ...
fun intersection ([]    : ''a list, ys : ''a list) = ...
  | intersection (x::xs : ''a list, ys : ''a list) = ...
您可能认为需要通过对
xs
ys
上的空/非空列表进行模式匹配来对列表使用递归。我在这里选择了
xs
,因为它恰好是第一个参数,但这是任意的:

fun intersection ([],    ys) = ...
  | intersection (x::xs, ys) = ...
或带有注释的类型:

fun intersection (xs : ''a list, ys : ''a list) = ...
fun intersection ([]    : ''a list, ys : ''a list) = ...
  | intersection (x::xs : ''a list, ys : ''a list) = ...
然后你可以问自己:

  • 空列表/集合与
    ys
    之间的交叉点是什么
  • x
    x::xs
    ys
    交叉点的一部分吗
  • 哪些其他元素可能是该交叉点的一部分(递归)

  • 你需要递归,你需要研究集合交的定义。