Warm tip: This article is reproduced from serverfault.com, please click

其他-haskell使用Foldl的Elem函数的自己的版本

(其他 - haskell Own version of Elem function using Foldl)

发布于 2020-11-29 13:37:55

我正在尝试创建自己的elem函数版本,该函数将返回xTrueFalse基于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]
   |            

                                                       ^^
Questioner
enneenne
Viewed
11
Willem Van Onsem 2020-11-29 21:45:34

使用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方法循环