代码之家  ›  专栏  ›  技术社区  ›  Sridhar Ratnakumar

或内部错误处理

  •  1
  • Sridhar Ratnakumar  · 技术社区  · 6 年前

    是否有一种Haskell模式可以避免编写此自定义函数?想法是将“无”作为错误处理(作为包装的一部分):

    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
    
    4 回复  |  直到 6 年前
        1
  •  6
  •   castletheperson    6 年前

    首先,您可以使用 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
    
        2
  •  3
  •   chi    6 年前

    原始代码已经很好了。您可能希望通过将每个分支保持在同一行上,使其占用更少的行。

    否则,仅出于备选方案的考虑,您可以使用:

    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
    

    我认为原始代码比后一种选择更具可读性。

        3
  •  2
  •   willeM_ Van Onsem    6 年前

    也许不是最简单的函数,但尝试使用单子和 Maybe 亚同态 例如:

    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 在里面 右x .

        4
  •  2
  •   Daniel Wagner    6 年前

    我会使用 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
    
    推荐文章