我是haskell新手。我的练习是编写一个谓词来检查一个元素是否存在于列表中。但我必须解决使用线性递归过程没有模式匹配。
isPresentRecNonPM :: Int -> [Int] -> Bool
isPresentRecNonPM y (x:xs)
| null xs = False
| y == x = True
| otherwise = isPresentRecNonPM y xs
那是我的代码,但是我找不到我的错误。你能帮我吗?我的代码有什么问题?您过早地返回了False
,因为null xs
检查非空列表参数的尾部是否为空。
isPresentRecNonPM :: Int -> [Int] -> Bool
isPresentRecNonPM _ xs | null xs = False
isPresentRecNonPM y (x:xs)
| y == x = True
| otherwise = isPresentRecNonPM y xs
既然你应该避免模式匹配,我怀疑你也不应该使用(x:xs)
,并在确认参数不为空后显式地使用head
和tail
。
isPresentRecNonPM :: Int -> [Int] -> Bool
isPresentRecNonPM y xs
| null xs = False
| head xs == y = True
| otherwise = isPresentRecNonPM y (tail xs)
(如果他们真的不使用模式匹配,您还需要避免不可辩驳的模式y
和xs
,并以无点样式定义函数。)
你正在使用模式匹配。实际上,您使用(x:xs)
,这是列表类型的模式。您应该使用xs
来匹配整个列表,因此:
isPresentRecNonPM :: Int -> [Int] -> Bool
isPresentRecNonPM yxs
| nullxs= False
| y == headxs= True
| otherwise = isPresentRecNonPM y (tailxs)
你可以进一步简化它:
isPresentRecNonPM :: Int -> [Int] -> Bool
isPresentRecNonPM y = go
where go xs
|nullxs = False
| y ==headxs = True
| otherwise = go (tailxs)
我们可以把它写成:
isPresentRecNonPM :: Int -> [Int] -> Bool
isPresentRecNonPM y = go
where go xs = not (null xs) && (y == head xs || go (tail xs))
话虽这么说,但由于head
和tail
是非全函数,因此通常使用模式匹配会更好。
由于错误地使用了模式匹配,您没有处理空列表。
我很确定你根本不应该做任何单独的案例分析,而是考虑谓词为真的条件,并编写单个逻辑表达式。
当且仅当
此谓词为真- 列表不为空,和
- 您要查找的是第一个元素或,它位于列表的尾部。 在代码中,
isPresentRecNonPM y xs = not (null xs)
&& (y == head xs || isPresentRecNonPM y (tail xs))