Jules
Jules

Reputation: 15199

Predefined Haskell operator for applying pure values in an Applicative?

If I have a function (e.g. of type a -> b) wrapped in an Applicative and a value that can be applied to it (i.e. a value of type a in the above example), I can apply it as follows:

doSomething :: Applicative f => f (a -> b) -> a -> f b
doSomething wrappedFn arg = wrappedFn <*> (pure arg)

I find myself doing this a lot. Is there a standard, predefined operator somewhere that will make this code more concise, or do I need to define one myself? If the latter, is there a conventional name for it?

Upvotes: 1

Views: 159

Answers (2)

Zeta
Zeta

Reputation: 105876

Is there a standard, predefined operator somewhere that will make this code more concise…?

No.

… or do I need to define one myself?

Yes (unless you want to import external packages).

If the latter, is there a conventional name for it?

It's called (??) in lens, and some have other names. According to lens, it's a generalized variant of flip, which makes sense:

flip ::             (a -> b -> c) -> b -> a -> c
(??) :: Functor f => f   (b -> c) -> b -> f c

Substitute f with ((->) a and you get flip from (??). Therefore, you can call it generalized flip.

By the way, you don't need Applicative. Functor is enough:

gFlip :: Functor f => f (a -> b) -> a -> f b
gFlip f x = fmap ($x) f

Some examples:

ghci> gFlip [(+ 1),(* 2)] 2
[3, 4]
ghci> gFlip (++) "world" "hello"
"helloworld"

Upvotes: 6

duplode
duplode

Reputation: 34378

There actually is a moderately well-known version of this operator, namely, (??) from lens:

(??) :: Functor f => f (a -> b) -> a -> f b

Note the Functor constraint. It turns out that Applicative isn't necessary, as it can be defined as \f x -> ($ x) <$> f.

The canonical use case for (??) is with the function functor, as an infix flip:

GHCi> execState ?? [] $ modify (1:)
[1]

In the general case, it does exactly what you want:

GHCi> [negate] ?? 3
[-3]

(Personally, I still find [negate] <*> pure 3 more readable, but YMMV.)

Upvotes: 3

Related Questions