【问题标题】:Retrieving values from a chain of ADT's with Maybe's使用 Maybe's 从 ADT 链中检索值
【发布时间】:2013-01-25 19:13:12
【问题描述】:

我有一些 ADT,每个 ADT 可能包含也可能不包含另一个 ADT。我需要从较低级别检索数据,并且我正在编写一些非常重复的代码,我确信这些代码可以被消除。我在 Real World Haskell 和“Learn You a Haskell For Great Good”中查看了一些示例代码,但我不太明白。这是一个与 ADT 无关的细节的示例。

  T24Report
      - projTitle :: Maybe ProjectTitle
            - zip :: Maybe String

要从 StreetAddress 检索邮政编码,我一直这样做:

 projNameStr :: T24Report -> String
 projNameStr t24 = if isNothing projTitleMaybe
                    then ""
                    else (fromMaybe "") $ zip $ fromJust projTitleMaybe
                where
                    projTitleMaybe = projTitle $ project t24

随着对象链的深度增加,代码的重复性也会增加。肯定有更好的办法。想法?参考?我在 StackOverflow 上找不到类似的问题,但我相信它一定在这里......这似乎是一个必须被问到的简单问题。

谢谢, 蒂姆

【问题讨论】:

  • 听起来你应该使用 Maybe 作为单子。
  • 看看maybe函数,案例分析,以及Maybe的Monad/Applicative实例。就个人而言,我很少使用isNothingfromJust
  • 谢谢——我会去重新阅读有关 monad 的信息,看看我是否能理解它。
  • Control.Lens 库(或一般的镜头)在这种情况下可能非常有用,尤其是在您想要更改嵌套记录时。从内到外重构一个新的类型实例来表示变化是很乏味的。
  • 我会调查的,谢谢@MFlamer。

标签: haskell maybe


【解决方案1】:

在最一般的情况下,我会这样写:

projNameStr :: T24Report -> String
projName t24 = fromMaybe "" $ do
    title <- projTitle $ project t24
    zip title

关键是使用do 块来分解处理所有Nothing 案例。

但是,在这种特定情况下,由于链中只有两个 Maybes,我很想将其缩短一点:

projNameStr :: T24Report -> String
projName t24 = fromMaybe "" $ projTitle (project t24) >>= zip

这正是上一个示例在编译期间转换为的内容。通常这种手动脱糖会使事情变得更糟,而不是更好。但在这种情况下,我会很想用这个,只是因为它短了几行,而且阅读的工作量太多

【讨论】:

  • 现在我可以了,所以我做到了。再次感谢@Carl
【解决方案2】:

Maybe 的 monad 实例是为解决这个确切的问题而构建的。如果你有一些对象,mayyX,mayyY 和 maybeZ,类型分别为 Maybe a,Maybe b 和 Maybe c,你可以这样做

do x <- maybeX
   y <- maybeY
   z <- maybeZ
   return (x,y,z)

这将具有类型 Maybe (a,b,c),如果三个 Maybe 中的任何一个为 Nothing,则最终结果将为 Nothing。

所以,在你的例子中,你会做这样的事情

projNameStr t24 = fromMaybe "" $ do t <- projTitle t24
                                    zip t

【讨论】:

  • 感谢您的解释。我想我忽略了显而易见的事情。我会赞成你的回答......但我的声望点低于 15 个要求
  • @tim93422:现在你可以了。 :)
  • @Vitus,现在我做到了。再次感谢!
猜你喜欢
  • 2014-02-15
  • 2020-04-25
  • 1970-01-01
  • 1970-01-01
  • 2016-08-11
  • 2014-10-31
  • 2020-11-15
  • 1970-01-01
  • 2023-02-02
相关资源
最近更新 更多