【问题标题】:Parse error in a case statement在 case 语句中解析错误
【发布时间】:2015-09-14 06:51:39
【问题描述】:

我正在尝试像这样在 Haskell 中将 Maybe Int 转换为 Int:

convert :: Maybe Int -> Int
convert mx = case mx of 
               Just x -> x
              Nothing -> error "error message"

当我编译它时,Haskell 告诉我:parse error on input 'Nothing'

我需要这个,因为我想使用 Data.List 模块中的 elem.Index 函数获取列表中元素的索引,然后在 take 函数上使用这个索引。我的问题是elemIndex 返回一个Maybe Int,但take 需要一个Int

【问题讨论】:

  • 我希望你明白,以这种方式“转换”并不是一个聪明的主意:你本质上是在颠覆类型系统。仅当您完全确定参数是 Just,但类型检查器无法证明时才这样做。即便如此,最好在您需要的地方明确匹配case mx of {Just x -> x},而不是通过辅助函数。原因是:如果这个匹配确实失败,它会给你一个很好的清晰的错误信息,告诉你它发生在哪里。当假设失败时,您的 convert 将始终为您提供相同的错误消息,无论您在哪里使用它。
  • 听起来你只需要takeWhile (/= item)

标签: haskell pattern-matching type-conversion parse-error maybe


【解决方案1】:

这是一个空格问题。 case 子句需要缩进到同一级别。

convert :: Maybe Int -> Int
convert mx = case mx of 
               Just x -> x
               Nothing -> error "error message"

记住只使用空格,不要使用制表符。

【讨论】:

  • 也就是说,OP 似乎想要的是fromJust
  • @bereal: 嗯……我不推荐fromJust。请参阅我上面对问题的评论。 (不过还是比convert 好。)
【解决方案2】:

为了补充@leftaroundabout 的答案,我想我可能会为您提供一些其他选择。

首先,你不应该做出这样不安全的事情:你的程序会失败。将其保留为 Maybe Int 并安全地运行会更清洁。换句话说,这是一个简单的解析错误,但像这样制作不完整的函数可能会在未来导致更大的问题。

你遇到的问题,我该怎么办?

我们可能会做一个更好的函数,像这样:

mapMaybe :: (a -> b) -> Maybe a -> Maybe b
mapMaybe f m = case m of
     Just a  -> f a
     Nothing -> Nothing

这会让你写:

λ> (+ 15) `mapMaybe` Just 9
Just 24

但是,有一个名为 fmap 的函数,它将函数“映射”到某些数据结构上,包括 Maybe

λ> (== 32) `fmap` Just 9
Just False

如果你有imported Control.Applicative,那么它有一个很好的运算符同义词:

λ> show <$> Just 9
Just "9"

如果您想进一步了解这些称为 Functor 的数据结构,我建议您阅读Learn-you a Haskell

【讨论】:

    猜你喜欢
    • 2014-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    相关资源
    最近更新 更多