在 Haskell 中,使用Maybe
andEither
比 Scala 更灵活一些,所以也许你可能会重新考虑这种方法。如果您不介意,我将使用您的第一个示例来说明这一点。
首先,您通常不会测试 null。相反,您只需计算您真正感兴趣的属性,Maybe
用于处理故障。例如,如果你真正想要的是列表的头部,你可以写这个函数:
-- Or you can just import this function from the `safe` package
headMay :: [a] -> Maybe a
headMay as = case as of
[] -> Nothing
a:_ -> Just a
对于纯粹是验证的东西,比如hasText
,那么你可以使用guard
,它适用于任何MonadPlus
类似的东西Maybe
:
guard :: (MonadPlus m) => Bool -> m ()
guard precondition = if precondition then return () else mzero
当您专注guard
于Maybe
monad时,就会return
变成:Just
mzero
Nothing
guard precondition = if precondition then Just () else Nothing
现在,假设我们有以下类型:
foo :: [A]
bar :: SomeForm
hasText :: SomeForm -> Bool
magic :: A -> SomeForm -> B
我们可以处理两者的错误,foo
并使用monad的符号bar
安全地提取magic
函数的值:do
Maybe
example :: Maybe B
example = do
a <- headMay foo
guard (hasText bar)
return (magic a bar)
如果您熟悉 Scala,do
则符号类似于 Scala 的推导式。上面的代码去糖:
example =
headMay foo >>= \a ->
guard (hasText bar) >>= \_ ->
return (magic a bar)
在Maybe
monad 中,(>>=)
并return
有以下定义:
m >>= f = case m of
Nothing -> Nothing
Just a -> f a
return = Just
...所以上面的代码只是简写:
example = case (headMay foo) of
Nothing -> Nothing
Just a -> case (if (hasText bar) then Just () else Nothing) of
Nothing -> Nothing
Just () -> Just (magic a bar)
...您可以将其简化为:
example = case (headMay foo) of
Nothing -> Nothing
Just a -> if (hasText bar) then Just (magic a bar) else Nothing
do
...这可能是您在没有or的情况下手写的内容guard
。