<p>I don't find the <code>Applicative</code> interface of applying lifted functions (namely, <code>(&lt;*&gt;)</code>) a good intuition. Functions are more complicated to conceptualize for various reasons.</p>
<p>I prefer thinking of <code>Applicative</code> as lifting an <em>n</em>-ary function</p>
<pre class="lang-hs prettyprint-override"><code>liftA0 :: Applicative f =&gt; (a)                -&gt; (f a)
liftA  :: Functor     f =&gt; (a -&gt; b)           -&gt; (f a -&gt; f b)
liftA2 :: Applicative f =&gt; (a -&gt; b -&gt; c)      -&gt; (f a -&gt; f b -&gt; f c)
liftA3 :: Applicative f =&gt; (a -&gt; b -&gt; c -&gt; d) -&gt; (f a -&gt; f b -&gt; f c -&gt; f d)
</code></pre>
<p>where <code>liftA0 = pure</code> and <code>liftA</code> already exists as <code>fmap</code> defined in terms of <code>Applicative</code>.</p>
<p>The thing is that 0-ary and 1-ary liftings</p>
<pre><code>liftA0 @f @a    :: Applicative f =&gt; a -&gt; f a
liftA  @f @a @b :: Applicative f =&gt; (a -&gt; b) -&gt; (f a -&gt; f b)
</code></pre>
<p>can both take an <code>a -&gt; b</code> function if we instantiate <code>liftA0 = pure</code> at a function type:</p>
<pre><code>liftA0 @f @(a-&gt;b) :: Applicative f =&gt; (a -&gt; b) -&gt; f (a-&gt;b)
liftA  @f @a @b   :: Applicative f =&gt; (a -&gt; b) -&gt; (f a -&gt; f b)
</code></pre>
<p>So <code>pure @f @(a-&gt;b)</code> already has that type.</p>
<p>And <code>pure</code> has plenty of purposes, theoretical which turn out to be practical in Haskell, it is the unit if <code>Applicative</code> is viewed as a <code>Monoid</code> in the category of natural transformations, with (<a href="https://arxiv.org/pdf/1406.4823.pdf" rel="nofollow noreferrer">Notions of Computation as Monoids</a>) with <a href="https://hackage.haskell.org/package/kan-extensions-5.2.3/docs/Data-Functor-Day.html" rel="nofollow noreferrer"><code>Day</code></a></p>
<pre><code>type Mempty :: Type -&gt; Type
type Mempty = Identity

type Mappend :: (Type -&gt; Type) -&gt; (Type -&gt; Type) -&gt; (Type -&gt; Type)
type Mappend = Day

mempty :: Applicative f =&gt; Mempty ~&gt; f
mempty (Identity a) = pure a

mappend :: Mappend f f ~&gt; f
mappend (LiftA2 (·) as bs) = liftA2 (·) as bs
</code></pre>
<p>I just released a library that works with <code>Applicative</code> homomorphisms, that are polymorphic functions that respect the applicative structure. It defines a type class for such structures</p>
<pre class="lang-hs prettyprint-override"><code>type  Idiom :: k -&gt; (Type -&gt; Type) -&gt; (Type -&gt; Type) -&gt; Constraint
class (Applicative f, Applicative g) =&gt; Idiom tag f g where
  idiom :: f ~&gt; g
</code></pre>
<p>where <code>pure</code> is the <a href="https://hackage.haskell.org/package/idiomatic-0.1.1.0/docs/Generic-Applicative-Idiom.html#t:Initial" rel="nofollow noreferrer">initial applicative morphism</a>.</p>
<pre class="lang-hs prettyprint-override"><code>-- https://chrisdone.com/posts/haskell-constraint-trick/
instance (Identity ~ id, Applicative f) =&gt; Idiom Initial id f where
  idiom :: Identity ~&gt; f
  idiom (Identity a) = pure a
</code></pre>
<p><code>pure</code> is then frequently used, as a unit for a computation. It is the driving force in <code>Traversable</code> one of the success stories of Haskell</p>
<pre class="lang-hs prettyprint-override"><code>instance Traversable [] where
  traverse :: Applicative f =&gt; (a -&gt; f b) -&gt; ([a] -&gt; f [b])
  traverse f []     = pure []
  traverse f (x:xs) = ...
</code></pre>
<p>we require <code>pure</code> because our only argument that produces an <code>Applicative</code>-action is <code>f x</code> but with an empty list we don't have an <code>x :: a</code> to feed it. Thus, we need 0-ary lifting.</p>
Why type of pure is a -> f a, not (a -> b) -> f (a -> b) on Applicative?
<p>Pure is used to transform normal function into function in <code>Applicative</code> container. With this, any multi-parameter operations become can be used on <code>Applicative</code>. In this context, pure is not desired to be <code>a -&gt; f a</code> type, it is just desired to be <code>(a -&gt; b) -&gt; f (a -&gt; b)</code> type. But type of <code>pure</code> is <code>a -&gt; f a</code>. Why should normal values can be transformed into <code>Applicative</code>? Is there more purpose for use <code>pure</code> more than transforming functions?</p>