在Haskell中合并/追加Justs

Dea*_*nes 9 monads haskell applicative maybe

我试图去做我们必须在Haskell,这是去是再明显Just [1]Just [2]Just [1, 2].但是我在网上找不到任何东西,因为我一直在寻找相关但无益的页面.那么,你是如何实现这一目标的?

ehi*_*ird 16

你可以使用liftA2 (++):

liftA2 (++) :: Maybe [a] -> Maybe [a] -> Maybe [a]
Run Code Online (Sandbox Code Playgroud)

liftA2只是将二进制函数提升为一个Applicative.Applicatives被设计用于在上下文中提升任意参数的函数,因此它们是完美的.在这种情况下,Applicative我们正在使用的是Maybe.要了解其工作原理,我们可以查看定义:

liftA2 :: (Applicative f) => (a -> b -> c) -> f a -> f b -> f c
liftA2 f a b = f <$> a <*> b
Run Code Online (Sandbox Code Playgroud)

(<$>)只需将纯值上的任何函数提升为一个在内部运行的函数f:(a -> b) -> f a -> f b.(fmap如果你熟悉Functors ,它只是一个别名.)对于Maybe:

_ <$> Nothing = Nothing
f <$> Just x = Just (f x)
Run Code Online (Sandbox Code Playgroud)

(<*>)有点棘手:它将一个函数应用于内部f的值f:f (a -> b) -> f a -> f b.用于Maybe:

Just f <*> Just x = Just (f x)
_ <*> _ = Nothing
Run Code Online (Sandbox Code Playgroud)

(其实f <$> x是同样的事情pure f <*> x,这是Just f <*> xMaybe.)

所以,我们可以扩展定义liftA2 (++):

liftA2 (++) a b = (++) <$> a <*> b

-- expand (<$>)
liftA2 (++) (Just xs) b = Just (xs ++) <*> b
liftA2 (++) _ _ = Nothing

-- expand (<*>)
liftA2 (++) (Just xs) (Just ys) = Just (xs ++ ys)
liftA2 (++) _ _ = Nothing
Run Code Online (Sandbox Code Playgroud)

实际上,我们可以使用这些运算符将任意数量的参数的函数提升为任意参数Applicative,只需遵循以下模式即可liftA2.这称为applicative样式,在惯用的Haskell代码中非常常见.在这种情况下,(++) <$> a <*> b如果a并且b已经是变量,通过写入直接使用它甚至可能更惯用.(另一方面,如果你部分应用它 - 比如说,将它传递给更高阶的函数 - 则更liftA2 (++)可取.)

每一个Monad都是一个Applicative,所以如果你发现自己试图将一个功能"提升"到一个环境中,Applicative那么你可能正在寻找它.

  • @DeanBarnes:`(2 :) <$>只是[3]` (4认同)
  • 别客气!:)为了概括@JoeyAdams所说的,`(xs ++)<$> mys`用于在`mys :: Maybe [a]`中添加任何`xs :: [a]`. (2认同)