【问题标题】:Defining a function in Haskell that returns true if it is the list consisting of 'a', false otherwise在 Haskell 中定义一个函数,如果它是由 'a' 组成的列表,则返回 true,否则返回 false
【发布时间】:2013-08-10 17:54:17
【问题描述】:

我是 Haskell 的新手,我正在尝试编写一个接受列表并返回布尔值的函数。

如果它的输入列表是只包含'a'的列表,它将返回True,否则返回False

这是我的最佳猜测:

f :: [a] -> Bool

f ('a':[]) = True

f (x:xs) = False

编译失败,返回:

Couldn't match type `a' with `Char'
  `a' is a rigid type variable bound by
      the type signature for f :: [a] -> Bool at charf.hs:6:1
In the pattern: 'b'
In the pattern: 'b' : []
In an equation for `f': f ('b' : []) = True

我的逻辑有什么错误?

【问题讨论】:

  • 你的意思是列表应该只包含一个Char'a'吗?在这种情况下,您的函数应该具有类型[Char] -> Bool。目前签名允许任何类型的列表,这就是您收到错误的原因。
  • 请注意,您可以简单地使用f x = x=="a",或者更简洁地使用f = (=="a")

标签: haskell pattern-matching


【解决方案1】:
f :: [Char] -> Bool
f ['a'] = True
f _ = False

使用模式匹配。您的函数似乎无法处理空列表。此外,您的函数不能像您想要的那样是通用的,因为它显然需要 [Char](或 String)。

【讨论】:

  • [a] 指的是任何类型的列表,对吧?所以我可以定义一个函数,它接受一个列表,如果第一个元素是“a”则返回 true,否则返回 false,或者至少这是我的目标。
  • 您不能这样做,因为您明确使用了Char。如果您尝试使用 alpha 列表,则不能在签名中的任何位置指定类型。
  • 在map的例子中,a可以和b同类型,但不一定。考虑map (const True) "foo"。如果map :: (a -> a) -> [a] -> [a],那么您确实只能生成与原始列表相同类型的列表。
  • @user2666425 您可以在通用列表上进行模式匹配。您不能对元素类型做出任何假设。当您在a 周围加上单引号时,您的意思是该列表必须匹配一个Char,其值为字符'a'。如果您删除引号,那么 a 将是一个匹配任何类型的变量,并且您的函数将适用于任意列表。
  • @user2666425 我认为您对 Haskell 中类型变量的工作方式存在误解。 [a] 类型并不意味着“一个列表,其中每个元素都可以是任何类型的值”,而是“一个列表,其元素都是来自一个单一类型的值,可以是任何类型”。因此,当您处理该列表时,您可以对元素做的唯一事情是对任何类型的 any 值有效的事情。只有 Char 值可以与 'a' 进行模式匹配,因此您无法匹配该模式(或任何其他模式,事实上)。
【解决方案2】:

如果要创建一个函数来测试列表是否包含单个给定值,则需要进行一些更改。

首先,您需要提供要比较的预期值。目前您正尝试与Char 'a' 进行比较,但您无法将Char 与某些未知类型a 进行比较。其次,这个类型需要是Eq类的一个实例,这样你才能进行比较。

您可以对单例列表进行模式匹配,然后添加一个子句以将元素与您期望的元素进行比较,例如

isSingletonOf :: Eq a => a -> [a] -> Bool
isSingletonOf v [s] | v == s = True
isSingletonOf _ _ = False

然后你可以创建一个函数来比较[Char]

f :: [Char] -> Bool
f = isSingletonOf 'a'

【讨论】:

    【解决方案3】:

    您也可以使用 Data.List 中定义的函数 elem 来执行此操作。

    这里是文档链接:
    http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-List.html#v:elem
    (如果你想看看它是如何实现的,你可以点击行尾的源代码)

    f :: [Char] -> Bool
    f = elem 'a'

    关于您对map 类型的回答。正如你所说:
    map :: (a -> b) -> [a] -> [b]

    toUpper :: Char -> Char

    因此
    map toUpper :: [Char] -> [Char]

    如果你要定义一个函数g :: String -> Int 那么
    map g :: [String] -> [Int]
    如您所见,根据您作为map 的第一个参数提供的函数,结果函数的输入和输出类型可能相同,也可能不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-23
      • 2013-09-14
      • 1970-01-01
      • 1970-01-01
      • 2018-10-22
      • 2016-08-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多