确定value是否是Haskell中列表的元素

时间:2017-09-18 21:17:28

标签: haskell recursion

我正在尝试编写一个函数来确定列表中是否存在元素,这两个元素都由用户提供。我认为递归解决方案是最好的。这就是我所拥有的:

isElement :: a -> [b] -> Bool
isElement a [] = False
isElement a (x:xs) = if a == x then True
                     else isElement a xs

但它无法编译。错误是“无法将预期类型-a与实际类型-b'匹配”。我不知道这意味着什么或如何解决问题。

1 个答案:

答案 0 :(得分:5)

您的代码在技术上有效。它是在这里给你带来麻烦的类型签名。

首先,这是工作代码:

isElement :: (Eq a) => a -> [a] -> Bool
isElement a [] = False
isElement a (x:xs) = if a == x then True
                     else isElement a xs

我改变了两件事:

  1. 使用Haskell的链表(使用[]的数据类型)时要记住的第一件事是它们只能包含相同类型的元素。但是,在您的类型签名a ➞ [b]中,您指定要求您的第一个元素属于a类型,而类型b列表中的元素则不同于a
  2. 第二件事是"启用"使用泛型类型ab进行等式检查,并且GHC会向您发出警告,其中包含要遵循的步骤以解决此问题:

    • No instance for (Eq a) arising from a use of ‘=='
      Possible fix:
        add (Eq a) to the context of
          the type signature for:
            isElement :: a -> [a] -> Bool
    

    所以它告诉我们的是指定可以比较a类型!
    这很棒,因为我们完全可以通过在代码中使用(Eq a) =>部分给编译器提供线索,大致转换为"给定数据类型a的此属性(Eq) ,[在此处插入类型签名]"。 (请随时在这里纠正我,StackOverflow的人!)

  3. 你的代码有效,并且通过这种显式递归重新实现函数是我如何首先了解它的工作方式,所以不要犹豫,通过重写你使用的东西来学习,然后在Hackage上检查它们的来源看看现实世界的哈克勒人是如何做到的。

    玩得开心!