我正在尝试创建自己的elem
函数版本,该函数将返回xTrue
或False
基于x是否在给定数组内。
elem' :: Eq(t)=>t->[t]->Bool
elem' x xs = or [foldl (\acc -> \a -> if a == x then True else False) [] xs]
我在这里想要做的是使用具有真/假值的foldl填充数组,然后生成or
函数,如果其中至少有一个是真(那么我想要得到),它将返回真。但是,此代码导致以下编译错误:
main.hs:11:71: error:
* Couldn't match expected type `Bool' with actual type `[a0]'
* In the second argument of `foldl', namely `[]'
In the expression:
foldl (\ acc -> \ a -> if a == x then True else False) [] xs
In the first argument of `or', namely
`[foldl (\ acc -> \ a -> ...) [] xs]'
|
11 | elem' x xs = or [foldl (\acc -> \a -> if a == x then True else False) [] xs]
|
^^
使用a的想法foldl
是不制作元素列表,因此也不使用or
。
如果使用foldl
,则万一a == x
失败,你将查看elem
前面的元素是否成功,因此acc
在这种情况下我们将返回。此外,你不能将其[]
用作累加器的“起始值”,因为foldl
应当返回Bool
,而不是列表:
elem' :: (Foldable f, Eq t) => t -> f t -> Bool
elem' x xs = foldl (\acc a -> if a == x then True else acc) False xs
但是,在这里使用并不是一个好主意foldl
,因为这意味着我们将对整个列表进行枚举。如果使用foldr
,我们可以从找到元素的那一刻起停止,因此我们可以将其重写为:
elem' :: (Foldable f, Eq t) => t -> f t -> Bool
elem' x = foldr (\e -> if x == e then const True else id) False
如果我们这样检查:
elem' 1 ([1,4,2,5] ++ repeat 3)
它会True
为该foldr
方法返回,而将为该foldl
方法循环。