在 Haskell 中将一个函子映射到另一个函子

Mapping a functor to another in Haskell

我有一个生成 Maybe a 类型的函数,我在函数中使用它来生成 Either b a。有没有一种方法可以将 Nothing 映射到 Left x 以简化我的代码?以下代码提供了一些上下文:

rmX :: ... -> Maybe a
cvX :: ... -> Either CVXError a
data CVXError = BadIndex | NoCover | NoSpace
cvX ... =
  ...
  case rmx 1 xs of
    Nothing -> Left NoSpace
    Just p  -> Right (x2:x1:(fromJust (rmX (-1) p)))
-- given that rmX always passes on negative value arg

case 语句只是请求用 fmap 替换,但问题是我不确定如何 'map' NothingLeft NoSpace fmap 调用甚至提取此模式以创建我自己的 util 函数。

您正在查找 maybe 函数:

cvX ... =
  ...
  maybe (Left NoSpace) (\p -> Right (x2:x1:(fromJust (rmX (-1) p)))) $
    rmX 1 xs

在这种情况下,值得一提的是 errors package. It offers a number of functions for juggling Maybe, Either and related types, including note,它“[标记] MaybeNothing 值”:

note :: a -> Maybe b -> Either a b
cvX ... =
  ...
  note NoSpace $ fmap (\p -> x2:x1:(fromJust (rmX (-1) p))) (rmX 1 xs)

不出所料,note 的实现使用 maybe 与 Sebastian Redl 的答案完全一样。

P.S.: 使用 fromJust 总是有点不愉快,因为它在给定 Nothing 时会失败。如果 rmX (-1) 无法生成 Nothing,您可能需要考虑分解出一个单独的函数,该函数不使用 return Maybe a 来代替 fromJust (rmX (-1) p)

一个类似的选择是使用 Maybe monad 直到最后,然后根据需要应用 LeftRight maybe.

maybe (Left NoSpace) Right $ do
     p1 <- rmX 1 xs
     p2 <- rmX (-1) p1
     return (x2:x1:p2)

这里有很大的调整空间,具体取决于您对 do 表示法与 >>= 的偏好:

-- untested; take these with a grain of salt...

maybe (Left NoSpace) Right $ do
    p <- rmX 1 xs >>= rmX (-1) 
    return (x2:x1:p)

maybe (Left NoSpace) Right (rmX 1 xs >>= rmX (-1) >>= (return . (x1:)) >>= (return . (x2:)))

-- etc