【发布时间】:2026-02-08 11:20:15
【问题描述】:
我需要在类型为Array Int Int 的may 数组中获取元素的位置。我找到了方法elemIndex 或find 来获取位置。我的问题是,例如,我不需要前缀 Just 5。那么在我的示例中,我如何只获得号码 5?
【问题讨论】:
-
如果元素不在列表中,你想返回什么?
我需要在类型为Array Int Int 的may 数组中获取元素的位置。我找到了方法elemIndex 或find 来获取位置。我的问题是,例如,我不需要前缀 Just 5。那么在我的示例中,我如何只获得号码 5?
【问题讨论】:
要安全地从Maybe a 值中提取值,您可以使用模式匹配,如下所示:
case elemIndex 'C' list of
Just n -> "You can find C at position " ++ show n
Nothing -> "There is no C in the list."
这将返回类似
"You can find C at position 2"
或
"There is no C in the list."
取决于列表中是否有 C。
当然,这种模式匹配一直很难写,所以有一个名为maybe 的函数可以做几乎相同的事情。如果你查看它的类型签名,你会发现
maybe :: b -> (a -> b) -> Maybe a -> b
因此,它采用b 类型的“默认值”和从a 到b 的函数,并将返回b。这是否是默认值取决于Maybe a 值是否存在或者是Nothing。例如,如果您想检查列表元素是否允许进入 18+ 俱乐部,您可以这样做
maybe False (\n -> n >= 18) (elemIndex 'C' list)
如果索引小于 18,则返回 False 或,如果元素不存在于列表中。如果确实存在,它会检查它是否大于等于18,然后返回True。
Just
到目前为止我已经告诉你的是如何以安全的方式摆脱Just。有时,你还不能摆脱Just——有时你没有合理的价值来返回如果你手上有一个Nothing而不是Just。然后您可以做的是在值仍在Just 内时对其进行操作。例如,要从 just 中的值中减去 15,您只需这样做
fmap (subtract 15) (Just 23)
将返回
Just 8
所以你会看到fmap 是如何获取Just something 值并将函数应用于其中的something 部分,将Just 保留在外面。如果你愿意
fmap (subtract 15) Nothing
它只会保留Nothing,所以结果是
Nothing
Maybe 很棒,因为它是一个错误处理系统,可以迫使您正确行事。您不能忽略错误的可能性(由Nothing 表示。)另一个常见的错误处理系统对此很糟糕。该系统是例外系统。没有人会知道您是否公然忽略可能发生的异常,这是非常不安全的程序的基础。
所以你真的想要保留Just,直到你可以把它扔掉同时用合理的东西替换潜在的Nothing值。
如果您可以保证Nothing 值的可能性没有。如果您确定每次调用elemIndex 时元素都会出现在列表中的某个位置,那么可以使用fromJust。 fromJust 会盲目地尝试从 Just 中取出一个值,而不关心如果那里没有 Just 会发生什么。如果出现问题,fromJust 只会炸毁你的程序(抛出异常)。
如您所知,您必须非常小心地使用它。
但是,正如 Jedai 在评论中指出的那样,即使您不应该能够获得 Nothing 值,也最好明确说明。不要使用fromJust,而是考虑做类似的事情
fromMaybe (error "The input " ++ show list ++ " shouldn't create a Nothing value!")
(elemIndex 'C' list)
它会弹出一个非常具体的错误消息,指出一定是哪里出了问题。
这当然和看起来像的模式匹配是一回事
case elemIndex 'C' list of
Just n -> n
Nothing -> error "The input " ++ show list ++ " shouldn't create a Nothing value!"
只压缩成标准的fromMaybe 函数。
【讨论】:
使用Data.Maybe 中的fromJust。喜欢:
fromJust $ elemIndex 2 [1,2,3,4,5]
你只会得到1。
但是,如果列表中没有所需的元素,这将失败,并且会出现异常:
*** Exception: Maybe.fromJust: Nothing
【讨论】:
fromJust,前提是您可以证明您要查找的元素存在于列表中。在任何其他情况下,Haskell 都具有出色的工具来操作 Maybe 值内的东西——所以你可以保留 Just 直到你确定你可以安全地删除它并仍然返回一个合理的值。
fromMaybe,它允许您指定默认情况(代表Nothing)并在其中放置一个精确的错误,以便您查明问题的根源如果你错了,因为默认的错误信息不会有太大帮助......所以像fromMaybe (error "Impossible ! The element should be in the list in this function _fun_") $ elemIndex...