使用递归确定子集
Determine subset using recursion
我正在尝试编写一个函数 subset
,它接受两个列表并确定第一个列表的元素是否出现在第二个列表中。
当输入如下函数时,代码会编译为 GHCi,但不会 运行(即卡住):
subset [1,2] [1,2]
这是我的代码:
subset :: (Eq a) => [a] -> [a] -> Bool
subset [] ys = True
subset (x:xs) ys
| elem x ys = subset (x:xs) ys
| otherwise = False
谢谢!
subset (x:xs) ys
| elem x ys = subset (x:xs) ys
-- ^^^^^^ --
注意上面的递归调用并没有改变参数!这将导致无限递归。您想在进行递归调用之前删除 x
。
让我们仔细看看您的代码片段:
subset (x:xs) ys
| elem x ys = subset (x:xs) ys
如果 elem x ys
成立,这是完全合理的,你有
subset (x:xs) ys = subset (x:xs) ys
它不会减少任何参数,只是重新重复相同的调用。
因此,无限循环。
在处理布尔值时,习惯上使用逻辑连接词,这通常会导致更简洁明了的定义:
subset (x:xs) ys = elem x ys && subset ..... .....
就是你所需要的,因为 (&&)
的真相 table 是
True && x = x
False && _ = False
即当第一个参数为假时,甚至不检查第二个参数的值。
不需要显式递归;您可以使用 all
来验证 (`elem` ys)
对于 xs
:
中的每个值都是正确的
subset xs ys = all (`elem` ys) xs
我正在尝试编写一个函数 subset
,它接受两个列表并确定第一个列表的元素是否出现在第二个列表中。
当输入如下函数时,代码会编译为 GHCi,但不会 运行(即卡住):
subset [1,2] [1,2]
这是我的代码:
subset :: (Eq a) => [a] -> [a] -> Bool
subset [] ys = True
subset (x:xs) ys
| elem x ys = subset (x:xs) ys
| otherwise = False
谢谢!
subset (x:xs) ys
| elem x ys = subset (x:xs) ys
-- ^^^^^^ --
注意上面的递归调用并没有改变参数!这将导致无限递归。您想在进行递归调用之前删除 x
。
让我们仔细看看您的代码片段:
subset (x:xs) ys
| elem x ys = subset (x:xs) ys
如果 elem x ys
成立,这是完全合理的,你有
subset (x:xs) ys = subset (x:xs) ys
它不会减少任何参数,只是重新重复相同的调用。
因此,无限循环。
在处理布尔值时,习惯上使用逻辑连接词,这通常会导致更简洁明了的定义:
subset (x:xs) ys = elem x ys && subset ..... .....
就是你所需要的,因为 (&&)
的真相 table 是
True && x = x
False && _ = False
即当第一个参数为假时,甚至不检查第二个参数的值。
不需要显式递归;您可以使用 all
来验证 (`elem` ys)
对于 xs
:
subset xs ys = all (`elem` ys) xs