You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Applicative类型的Dual等价实现:标准库或常用包中是否存在?

Hey, this is a really good question—you’re right to draw the parallel between Dual (for reversing Monoid's mappend) and a type that reverses Applicative's <*> order!

The good news is: this type actually exists in base (since version 4.6, so it’s been around for a while), you just might have missed it because it lives in a less obvious module. It’s called Backwards, and it’s defined in Control.Applicative.Backwards.

What Backwards does

It’s a simple newtype wrapper, exactly analogous to Dual, but tailored for Applicative:

newtype Backwards f a = Backwards { forwards :: f a }

Its Applicative instance reverses the order of <*> by using <**> (the flipped version of <*>):

instance Applicative f => Applicative (Backwards f) where
    pure = Backwards . pure
    Backwards f <*> Backwards x = Backwards (x <**> f)

Example of the reversed behavior

For applicatives where execution order matters (like IO), this makes the effect order flip:

import Control.Applicative.Backwards

main = do
  -- Normal Applicative order: runs "first" then "second"
  putStrLn "first" <*> pure ()
  putStrLn "---"
  -- Backwards order: runs "second" then "first"
  forwards $ Backwards (putStrLn "second") <*> Backwards (putStrLn "first")

Are there other implementations in common packages?

While Backwards in base is the standard go-to, you might find equivalent types in niche utility packages, but none are as widely used or maintained as the base version. If you’d defined your own Swap type, it would be functionally identical to Backwards—just a name difference.

内容的提问来源于stack exchange,提问作者rampion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:21:18