4

我有以下函数,其作用类似于索引运算符:

let {
  index :: [a]->Int->Maybe a
  index [] i = error "Empty list"
  index l i = if i <= ((length l) - 1) && i >= 0 then 
      Just(l !! i) 
    else
      error "Index out of bounds"
}

现在,最初我没有使用就写了这个Just(我仍然不明白谷歌搜索后它是什么):

let {
  index :: [a]->Int->Maybe a
  index [] i = error "Empty list"
  index l i = if i <= ((length l) - 1) && i >= 0 then
      (l !! i) 
    else
      error "Index out of bounds"
}

对我来说,上述功能非常有意义。因为这里我有一个函数,它接受一个“通用类型”列表,a一个Int是索引并返回Maybe类型的值a或引发运行时异常。但是,我不明白 GHCi 告诉我的地方:

<interactive>:1:120:
Couldn't match type `a' with `Maybe a'
  `a' is a rigid type variable bound by
      the type signature for index :: [a] -> Int -> Maybe a
      at <interactive>:1:34
Expected type: [Maybe a]
  Actual type: [a]
In the first argument of `(!!)', namely `l'
In the expression: (l !! i)

现在,为什么 GHCi 会与 type 的类型混淆,l为什么它需要一个 type 的列表Maybe a?最后,如何Just解决问题?

4

3 回答 3

6

您在类型注释中明确说明您的函数index返回一个Maybe a.

Maybe 是 Haskell 中定义的一种数据类型:

data Maybe a = Just a | Nothing

也就是说,它有两个值构造函数,Just :: a -> Maybe a并且Nothing :: Maybe a. 因此,为了让您的功能正常工作,它必须返回 aJust a或 a Nothing

这也意味着您应该能够稍微考虑一下删除错误语句并将实际错误编码为Nothing(即我们超出范围,这里没有元素!)并且仅Just a在有意义的情况下返回结果。

于 2012-07-26T20:52:57.413 回答
2

您告诉 GHC 的返回类型为indexas Maybe a。这意味着(l !! i)(返回的值index)必须是类型Maybe a

由于从(l !! i)列表中选择单个元素l,这意味着l必须是 type[Maybe a]才能使其元素之一成为Maybe a

但是l是第一个参数index,你也告诉 GHC 是输入的[a]

这正是你的错误。GHC 试图将索引编译为 a[Maybe a]以获得 a Maybe a,但发现被索引的东西是 a [a]

Just解决这个问题的原因是它Just的类型a -> Maybe a。因此,当您说 时Just (l !! i),GHC 现在看到您索引 a[a]以获得 a a,然后按预期应用Just到导致 a 的结果。Maybe a

于 2012-07-27T03:50:34.777 回答
1

从文档中,Data.Maybe

Maybe 类型封装了一个可选值。Maybe a 类型的值要么包含 a 类型的值(表示为 Just a),要么为空(表示为 Nothing)。

如果您正在寻找一种类型Maybe Int,那么您的函数将返回Nothing, 或Just Int

它是一种简单的错误单子,所有错误都由 Nothing 表示。

本质上,如果Nothing返回,则发生了某些事情,导致函数无法找到结果。Just限定符允许您对这些类型Maybe进行操作。

于 2012-07-26T20:53:34.573 回答