5

Class Applicative is declared as:

class Functor f   =>  Applicative f   where
pure  ::  a   ->  f   a
(<*>) ::  f   (a  ->  b)  ->  f   a   ->  f   b

We can represent fmapi, i=0,1,2,... in terms of pure and (<*>):

fmap0 ::  a   ->  f   a
fmap0 =   pure
fmap1 ::  (a  ->  b)  ->  f   a   ->  f   b
fmap1 g   x   =   pure    g   <*> x
fmap2 ::  (a  ->  b   ->  c)  ->  f   a   ->  f   b   ->  f   c
fmap2 g   x   y   =   pure    g   <*> x   <*> y
fmap3 ::  (a  ->  b   ->  c   ->  d)  ->  f   a   ->  f   b   ->  f   c   ->  f   d
fmap3 g   x   y   z   =   pure    g   <*> x   <*> y   <*> z

In applicative, how can <*> be represented in terms of fmap_i, i=0,1,2,...?

Thanks.

See also Is the implementation of `<*>` based on `fmap` special to Maybe applicative or can it be generalized to other applicatives?

Tim
  • 1
  • 141
  • 372
  • 590
  • 2
    If you could, you wouldn't need the `Applicative` typeclass. `<*>` allows you to extract a wrapped function in a way that `Functor` cannot. – chepner Jul 24 '19 at 17:37
  • However, `fmapi,i >=2 or i=0` must be satisfied by applicative not necessarily by functor. I suspect applicative can be defined fully in terms of `fmapi,i >=0` instead of `pure` and `<*>`. – Tim Jul 24 '19 at 17:40
  • Why? None of those `fmap` variants involve a *function* wrapped by the functor. – chepner Jul 24 '19 at 20:35
  • I was wondering what "a function wrapped by the functor" means? – Tim Jul 24 '19 at 20:47
  • 1
    @chepner, actually you can (as I'm 100% sure you know and are just having a mental blank). Tim's `fmap2` is the same as the standard `liftA2` which, together with `pure` (Tim's `fmap0`) is one valid minimal definition of an `Applicative`. As K.A.Buhr says in his answer, `(<*>)` can easily be defined in terms of it. That is, applying a "function wrapped in the functor" to an input value also wrapped in the functor can be done as soon as you have a way to lift any function of 2 arguments into the functor (because you just lift the function-application function). – Robin Zigmond Jul 24 '19 at 22:27
  • you already have it in your question. `f <*> x = id f <*> x = fmap id f <*> x = fmap1 id f <*> x = pure id <*> f <*> x = fmap2 id f x = liftA2 id f x`. thus `(<*>) = fmap2 id = liftA2 id`. ([see](https://stackoverflow.com/a/54962626/849891) [also](https://stackoverflow.com/a/53829742/849891)). – Will Ness Jul 26 '19 at 14:29
  • Why don't you accept the answer? Wasn't helpful to you? – developer_hatch Jul 29 '19 at 18:37

1 Answers1

9

You can write:

(<*>) = fmap2 ($)

or, if you find it less obscure:

f <*> a = fmap2 apply f a
  where apply g x = g x
K. A. Buhr
  • 45,621
  • 3
  • 45
  • 71
  • Thanks. I suspect applicative can be defined fully in terms of fmapi,i >=0 instead of pure and <*>. So I guess <*> can be represented in terms of only fmapi,i >=0 – Tim Jul 24 '19 at 17:46
  • 3
    You suspect correctly, but that would be massive overkill. You only need `pure` (your `fmap0`) and either `<*>` or `liftA2` (which you have called `fmap2`) to define an `Applicative`. So why add an infinite number of different superfluous methods to the class? Indeed it's the ability to "lift" functions of more than 2 arguments which `Applicative` is really all about, whereas `Functor` can only do it for functions of a single argument. (Incidentally, your `fmapk` are in the standard library as `liftAk`, for `k` in the range 2 to some arbitrary number (5 or so I think).) – Robin Zigmond Jul 24 '19 at 18:06
  • 1
    Too late to edit, but there's an important mistake in my comment above: *more than 2* should be *2 or more* – Robin Zigmond Jul 24 '19 at 18:23
  • Does `where apply g x = g x` define a function named `apply` which takes two arguments `g` and `x`? – Tim Jul 24 '19 at 19:16
  • 1
    Yes -- `apply g x = g x` has type `(a -> b) -> a -> b`. It takes two arguments, `g` and `x`, and applies `g` to `x`. In fact, `apply` is actually a specialization of `id`, so if you replace either `($)` or `apply` above with `id`, the definitions work fine too (i.e., `(<*>) = fmap2 id` and `f <*> a = fmap2 id f a`). – K. A. Buhr Jul 24 '19 at 20:25
  • Thanks. Is the implementation of `<*>` based on `fmap` special to Maybe applicative or can it be generalized to other applicatives? https://stackoverflow.com/questions/57220345/is-the-implementation-of-based-on-fmap-special-to-maybe-applicative-or-c – Tim Jul 26 '19 at 12:43