我经常有一个“也许没有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"
此处parseUSDate
的类型为Text -> Maybe Date
。
Aeson解析显然会返回Maybe Text
。
所以在我看来,我需要在这里提升2层Maybe
。我不知道如何以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"
答案 0 :(得分:10)
有一个非常方便的Control.Monad.join
功能:
> join (Just (Just 1))
Just 1
> join (Just Nothing)
Nothing
> join Nothing
Nothing
我不是Aeson的专家,但如果我这样做:
> :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)
这是你要找的东西吗?
编辑:修正了它实际上有效...我的初始通用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"
(这应该有用......)
答案 1 :(得分:6)
如果您有f' = maybe Nothing f
,则类型必须为f :: a -> Maybe b
和f' :: Maybe a -> Maybe b
(其中a
和b
可能是变量或特定类型),或者它不会进行类型检查。但这只是Maybe
monad的>>=
类型:Maybe a -> (a -> Maybe b) -> Maybe b
!因此maybe Nothing f
可以写成(>>= f)
。