【问题标题】:Simplifying nested Maybe pattern matching简化嵌套的 Maybe 模式匹配
【发布时间】:2013-10-29 10:40:23
【问题描述】:

我的代码中有以下构造:

f :: Maybe A -> X
f a = case a of
  Nothing -> x
  (Just b) -> case b of
    Nothing -> y
    (Just c) -> case c of
      Nothing -> z
      (Just d) -> d

我没有看到一个明显的方法来简化这个而不是使用嵌套的maybe 函数,这不会让整个事情看起来更好。有没有什么聪明的——但仍然可以理解的——技巧可以帮助这个结构更“优雅”?

【问题讨论】:

  • 你需要一个更好的结构来解决问题然后嵌套Maybe
  • 你不关心 b 和 c 的值,只关心它们是否有值,这似乎有点奇怪。这使得它们有效地布尔值。 Maybes层是任意深还是固定深度?
  • 你的模型基本上是错误的。您需要链接(即映射)函数/函子,而不是采用这种命令式风格。
  • @itsbruce:用简单的英语是什么意思? (又名,翻译功能是什么?)
  • 这里的答案没用,因为它们傲慢地暗示,你只有一个嵌套的 Maybe,而给定的例子不仅仅是一个更复杂 (一组函数也返回 Maybe 值,commeon 也是如此。

标签: haskell nested pattern-matching simplify maybe


【解决方案1】:

为什么代码首先构造了一个Maybe (Maybe (Maybe X)) 值?拆开这样的价值并不好,但真正的问题是,为什么会有这样的价值。也许代码会更好地避免所有那些嵌套的 Maybe。

如果你真的需要有这样的价值并且需要在所有Just/Nothing 的情况下做不同的事情,你必须把它们都写下来。但是,您可以将它们组合成一个大模式匹配,而不是多个嵌套的 case 语句:

f Nothing                = x
f (Just Nothing))        = y
f (Just (Just Nothing))  = z 
f (Just (Just (Just d))) = d

【讨论】:

  • 我正在解析一个包含许多“可为空”类型的嵌套 JSON 值,这就是为什么有这么多任意嵌套的 Maybes。
【解决方案2】:

尽管您对不使用 maybe 有限制,但我认为这看起来相当不错:

f = maybe x (maybe y (maybe z id))

甚至更好,正如@pat 在他的评论中所建议的那样:

f = maybe x . maybe y . maybe z $ id

【讨论】:

  • 或f = maybe x . maybe y . maybe z $ id
【解决方案3】:

更新 2

Monad Either 适合你

import Data.Maybe (maybe)

maybeE :: e -> Maybe a -> Either e a
maybeE e = maybe (Left e) Right

f :: Maybe (Maybe (Maybe d)) -> Either e d
f a  =   maybeE x a 
     >>= maybeE y
     >>= maybeE z

更新 3

如果我们不想Either类型,我们可以重写函数:

import Data.Either(either)

either' = either id id

f :: Maybe (Maybe (Maybe d)) -> d
f a = either' $ maybeE x a 
            >>= maybeE y
            >>= maybeE z

【讨论】:

  • 我不确定Maybe monad 在这里有什么帮助,a 的类型是Maybe (Maybe (Maybe ...))),并且在每个Maybe 层之后我必须返回一个不同的值,如果它计算结果为 Nothing,(在上面的示例中为 x y z)。
  • @PhilipK 哦,我明白了我的错误:我已经更新了我的答案
  • 这可以重写,以便 f 将任意大小的 Eitherss 列表作为单个参数。会更好,我想。但这是针对 OP 的评论,而不是您,viorior。
  • @itsbruce 如果您允许f 采用任意大小的Eithers 列表,它的类型会是什么?哦,你的意思不是嵌套的Maybes。
  • 没错! :) 它应该是f :: [something] -> d,其中something 可能只是被映射的函子,坦率地说。这种事情不需要比这更复杂。
猜你喜欢
  • 2014-04-21
  • 2022-01-11
  • 1970-01-01
  • 1970-01-01
  • 2013-09-13
  • 2019-01-03
  • 1970-01-01
  • 2011-08-11
  • 2017-12-16
相关资源
最近更新 更多