【问题标题】:What is Just in Haskell and why wouldn't this function work without it?什么是 Just in Haskell,为什么没有它这个函数就不能工作?
【发布时间】:2012-07-26 20:48:09
【问题描述】:

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

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 会与 l 的类型混淆,为什么它需要 Maybe a 类型的列表?最后,Just如何解决问题?

【问题讨论】:

  • Code-Guru,现在我的代码在您编辑后看起来很舒服 :)
  • 您真的更喜欢将您的定义写在您最初发布的单行上吗?
  • 实际上,我永远不会写这样的单行代码,因为我来自 C++/VB.NET 背景。由于 Haskell 为我提供了写-编译-执行或只写-执行的选项,我的懒惰更喜欢第二种选择。另外,我刚刚开始学习它,所以只有“玩具程序”才会这样写。也许我不知道我是否可以在 GHCi 中将我的代码拆分为多行,是吗?
  • LYAH 为初学者提供了关于 Maybe、Just 和 Nothing 的不错解释。 learnyouahaskell.com/…

标签: haskell types maybe


【解决方案1】:

您已在类型注释中明确指出,您的函数 index 返回一个 Maybe a

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

data Maybe a = Just a | Nothing

也就是说,它有两个值构造函数,Just :: a -&gt; Maybe aNothing :: Maybe a。因此,为了让您的功能正常工作,它必须返回 Just aNothing

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

【讨论】:

  • 为了对称起见,最好在关于构造函数的句子中写 Nothing :: Maybe a 而不是 Nothing,因为你已经给出了 Just 的类型,以防 OP 认为两者是不同的野兽。
  • 是的,我会阅读更多关于 value-ctors、datatypes 和 type-classes 的内容......我认为 Haskell 会很有趣...... :)
  • 类型非常重要。如果您不确定,可以省略类型注释,让 ghc 为您确定函数的类型。
【解决方案2】:

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

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

但是lindex 的第一个参数,您还告诉GHC 输入[a]

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

Just 修复此问题的原因是 Just 的类型为 a -&gt; Maybe a。因此,当您说 Just (l !! i) 时,GHC 现在会看到您对 [a] 进行索引以获取 a,然后将 Just 应用于导致 Maybe a 的结果,正如预期的那样。

【讨论】:

    【解决方案3】:

    来自文档,Data.Maybe

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

    如果您正在寻找类型 Maybe Int,那么您的函数将返回 NothingJust Int

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-25
      • 2014-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多