展平Maybes

Vag*_*rdi 1 haskell maybe

我经常有一个"也许没有someFunc"模式的代码:

instance FromJSON SaveSection where
  parseJSON (Object o) =
      SaveSection <$>
      o .:? "eventId" <*>
      (maybe Nothing parseUSDate <$> o .:? "eventDate") <*>
      o .:? "eventRecId" <*>
      o .:? "idxId" <*>
      (maybe Nothing parseUSDate <$> o .:? "idxDate") <*>
      o .:? "idxRecId"
Run Code Online (Sandbox Code Playgroud)

这里parseUSDate有类型Text -> Maybe Date.

Aeson解析显然会返回Maybe Text.

所以在我看来,我需要在Maybe这里提升2层.我不知道如何以任何其他方式做到这一点,但有maybe Nothing someFunc模式.

我错过了一些明显的"扁平化"或者我可以在这里使用的任何功能吗?

编辑:感谢Alexey的回答.

这正是我想要的.这是最终结果:

instance FromJSON SaveSection where
  parseJSON (Object o) =
      SaveSection <$>
      o .:? "eventId" <*>
      ((>>= parseUSDate) <$> o .:? "eventDate") <*>
      o .:? "eventRecId" <*>
      o .:? "idxId" <*>
      ((>>= parseUSDate) <$> o .:? "idxDate") <*>
      o .:? "idxRecId"
Run Code Online (Sandbox Code Playgroud)

bhe*_*ilr 10

有一个非常方便的Control.Monad.join功能:

> join (Just (Just 1))
Just 1
> join (Just Nothing)
Nothing
> join Nothing
Nothing
Run Code Online (Sandbox Code Playgroud)

我不是艾森的专家,但如果我这样做:

> :m Control.Monad Control.Applicative Data.Aeson Data.Text
> :set -XOverloadedStrings
> :set +m 
> let f :: Text -> Maybe Text
|     f = Just    -- Stand-in for parseUSDate
> :t \o -> join <$> liftM f <$> o .:? "key"
Object -> Parser (Maybe Text)
> -- Has the same type as your expression
> :t \o -> maybe Nothing f <$> o .:? "key"
Object -> Parser (Maybe Text)
Run Code Online (Sandbox Code Playgroud)

这是你要找的东西吗?

编辑:修复,以便它实际上工作...我的初始通用f :: a -> Maybe a是弄乱的东西.


您可以让操作员清理它:

infixl 9
(>>=$) :: (Functor f, Monad m) => f (m a) -> (a -> m b) -> f (m b)
m >>=$ a = join <$> liftM a <$> m

parseJSON (Object o) =
    SaveSection
        <$> o .:? "eventId"
        <*> o .:? "eventDate" >>=$ parseUSDate
        <*> o .:? "eventRecId"
        <*> o .:? "idxId"
        <*> o .:? "idxDate" >>=$ parseUSDate
        <*> o .:? "idxRecId"
Run Code Online (Sandbox Code Playgroud)

(这应该工作......)


Ale*_*nov 6

如果你有f' = maybe Nothing f,那么类型必须f :: a -> Maybe bf' :: Maybe a -> Maybe b(其中a,并b可能是变量或特定类型),否则将无法键入检查.但是,这仅仅是类型>>=Maybe单子:Maybe a -> (a -> Maybe b) -> Maybe b!所以maybe Nothing f可以写成(>>= f).

  • @AlexeyRomanov,哦,对,布拉诺.`(= <<)=也许没什么.(我更喜欢`(= <<)`,所以感觉更基本) (2认同)