【问题标题】:Checking whether element is in list or not检查元素是否在列表中
【发布时间】:2021-12-25 14:45:03
【问题描述】:

我刚刚开始在 Haskell 中编写我的前几个程序,而且我很努力 - 所以请原谅大量的错误。我在网上发现了这个练习题,它要我接受一个列表,一个 int,并返回一个 bool。我应该检查是否在列表中找到 int 并分别返回 true 或 false。 这就是我所拥有的:

import Data.List

elem':: (Eq a) => a -> [a] -> Bool
   elem' x [x] 
      | x == [x:xs] = True
      | length [x] == 1 = False
      | otherwise = elem' tail [x]

编译器返回

非法类型签名 [...] 类型签名只允许在带有 ScopedTypeVariables 的模式中

我还不能真正理解。我发现有人说使用制表符而不是空格时会发生此错误,但我只使用了空格。我很感激任何建议!

【问题讨论】:

  • 除非您使用的是包含单个元素的列表,否则我不会使用 [x]
  • 你为什么缩进elem' x [x]
  • 你的符号很乱。让x 成为元素(针)。让ys 成为列表(干草堆)。
  • 在很多情况下,当你需要在列表上定义一个函数时,你需要f [] = ...f (x:xs) = ...这两个case。尝试遵循该模式elem y [] = ...elem y (x:xs) = ...。避免使用head,tail,length,[x],[x:xs],因为它们通常会导致您找到错误和/或低效的解决方案。

标签: list haskell


【解决方案1】:

首先你有一个简单的缩进问题。您的定义被解析为

elem':: (Eq a) => a -> [a] -> Bool elem' x [x] 
      | x == [x:xs] = True
      | length [x] == 1 = False
      | otherwise = elem' tail [x]

我有点惊讶这没有被报告为 parse 错误,但基本上是一个。

您需要做的是,将所有函数子句缩进到 与签名相同的 级别(即在这种情况下,根本不缩进)。

elem':: (Eq a) => a -> [a] -> Bool
elem' x [x] 
 | x == [x:xs] = True
 | length [x] == 1 = False
 | otherwise = elem' tail [x]

这仍然是非常错误的。首先,您在x 上匹配了两次。这在 Haskell 中是不可能的。 OTOH 范围内没有变量 xs。如果是,它必须具有类型[a],然后[x:xs] 将具有类型[[a]]:嵌套列表。但是然后将其与x 进行比较,这甚至不是一个简单的列表,没有任何意义。 length [x] 始终为 1,无论 x 是什么。同样,tail [x] 始终是空列表(但这甚至不是这里使用的,您实际上已经写过 tail 函数应该作为参数传递给 elem')。

也许混淆是因为[ ] 可能意味着两种不同的东西:一个是类型级别,这意味着您正在谈论封闭类型的元素列表。 IE。 [a] 是其元素类型为 a 的列表的类型。
相比之下,在 级别上,[x] 专门是仅包含单个元素的列表,即 @ 987654339@.

您应该确保您了解模式匹配的工作原理。如果您的条款中有两个不同的变量,您的条款将是合法的。那么,匹配[y] 意味着这个子句只接受只有一个元素的列表,而y 将是单个元素的值。在这种情况下,正确的实现应该是

elem' x [y] = x==y

(或者,你可以在这里让守卫产生TrueFalse,但这只是多余的工作。)

实际上,虽然没有充分的理由为恰好一个元素设置一个子句。您只需要一个 zero 元素的子句

elem' x [] = ...

和一个至少一个元素的子句:

elem' x (y:ys)
 | ...
 | ...

【讨论】:

    猜你喜欢
    • 2021-12-17
    • 2014-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 2018-09-04
    • 1970-01-01
    相关资源
    最近更新 更多