Applicative 中等价于 Dual 的是什么?

4

Dual是一个新类型的封装器,它只是反转封装类型的Monoid实例中mappend的顺序:

>>> "hello" <> " " <> "world"
"hello world"
>>> getDual $ Dual "hello" <> Dual " " <> Dual "world"
"world hello"

同样地,也可以定义一个新类型包装器Swap,它反转所包装类型的Applicative实例中<*>的顺序:

newtype Swap f a = Swap { getSwap :: f a } deriving Functor
instance Applicative f => Applicative (Swap f) where
  pure = Swap . pure
  Swap mf <*> Swap ma = Swap $ (\a f -> f a) <$> ma <*> mf

>>> ("hello", replicate) <*> (" ", 5) <*> ("world", ())
("hello world", [(),(),(),(),()])
>>> getSwap $ Swap ("hello", replicate) <*> Swap (" ",5) <*> Swap ("world", ())
("world hello", [(),(),(),(),()])

我狂想着在base里有一个等效于Swap的函数,但是我似乎找不到它。是否有其他包中常用的等效函数?


如果有帮助的话,还有 <**> :: Applicative f => f a -> f (a -> b) -> f b - Simon Courtenage
1个回答

10

您正在寻找transformers' Control.Applicative.Backwards中的Backwards

-- | The same functor, but with an 'Applicative' instance that performs
-- actions in the reverse order.
newtype Backwards f a = Backwards { forwards :: f a }

-- etc.

-- | Apply @f@-actions in the reverse order.
instance (Applicative f) => Applicative (Backwards f) where
    pure a = Backwards (pure a)
    {-# INLINE pure #-}
    Backwards f <*> Backwards a = Backwards (a <**> f)
    {-# INLINE (<*>) #-}

(<**>)来自Control.Applicative,就像你所期望的那样:

-- | A variant of '<*>' with the arguments reversed.
(<**>) :: Applicative f => f a -> f (a -> b) -> f b
(<**>) = liftA2 (\a f -> f a)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接