是否有一个Haskell模式可以避免编写这个自定义函数?我的想法是将Maybe中的Nothing作为一个错误处理(作为包装的一部分):
eitherMaybeHandle :: String -> Either String (Maybe a) -> Either String a
eitherMaybeHandle err = \case
Left e ->
Left e
Right Nothing ->
Left err
Right (Just a) ->
Right a
答案 0 :(得分:5)
首先,您可以使用sequence
将Either a (Maybe b)
转换为Maybe (Either a b)
。然后,您可以将fromMaybe
与a
类型的值一起应用于结果,以获得Either a b
。
import Data.Maybe (fromMaybe)
eitherMaybeHandle :: a -> Either a (Maybe b) -> Either a b
eitherMaybeHandle err = fromMaybe (Left err) . sequence
答案 1 :(得分:3)
原始代码已经很好了。您可能需要考虑通过将每个分支保持在同一行来使其占用更少的行。
否则,只是为了替代方案,您可以使用:
eitherMaybeHandle :: String -> Either String (Maybe a) -> Either String a
eitherMaybeHandle _ (Left e) = Left e
eitherMaybeHandle err (Right Nothing) = Left err
eitherMaybeHandle _ (Right (Just a)) = Right a
甚至
eitherMaybeHandle :: String -> Either String (Maybe a) -> Either String a
eitherMaybeHandle _ (Left e) = Left e
eitherMaybeHandle err (Right x) = maybe (Left err) Right x
我认为原始代码比后一种代码更具可读性。
答案 2 :(得分:2)
也许不是最简单的功能,但尝试使用monad和Maybe
catamorphism ,如:
import Data.Maybe(maybe)
eitherMaybeHandle :: a -> Either a (Maybe b) -> Either a b
eitherMaybeHandle err = (>>= maybe (Left err) Right)
我们甚至可以删除err
参数,并将其写成:
eitherMaybeHandle :: a -> Either a (Maybe b) -> Either a b
eitherMaybeHandle = (=<<) . flip maybe Right . Left
由于Either a
是monad实例,因此我们可以使用>>=
。在这种情况下,我们保持Left x
不受影响,Right x
将通过该函数。
作为功能,我们使用maybe :: a -> (b -> a) -> Maybe b -> a
。因此,我们在Nothing
上映射Left err
,并在Right
中使用Just x
作为转换Right x
的函数。
答案 3 :(得分:2)
我会使用提供
的errors
包
note :: a -> Maybe b -> Either a b
可以与另一个Either
实例合并Monad
:
eitherMaybeHandle :: e -> Either e (Maybe a) -> Either e a
eitherMaybeHandle err act = act >>= note err