[GHC] #14855: Implementation of liftA2 for Const has high arity

GHC ghc-devs at haskell.org
Mon Feb 26 00:11:06 UTC 2018


#14855: Implementation of liftA2 for Const has high arity
-------------------------------------+-------------------------------------
        Reporter:  lyxia             |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  libraries/base    |              Version:  8.2.2
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  Runtime           |  Unknown/Multiple
  performance bug                    |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------
Description changed by lyxia:

Old description:

> {{{
> instance Monoid m => Applicative (Const m) where
>     pure _ = Const mempty
>     liftA2 _ (Const x) (Const y) = Const (x `mappend` y)
>     (<*>) = coerce (mappend :: m -> m -> m)
> }}}
>
> https://hackage.haskell.org/package/base-4.10.1.0/docs/src/Data.Functor.Const.html#line-69
>

> `(<*>)` is implemented with a `coerce` but `liftA2` isn't. Would the
> following not have better inlining behavior?
>
> {{{
>     liftA2 _ = coerce (mappend :: m -> m -> m)
> }}}
>
> Going further, should the unused argument also be moved to the RHS? What
> about `pure`? What are the pros and cons compared to this other
> alternative:
>
> {{{
>     pure = \_ -> mempty
>     liftA2 = \_ -> coerce (mappend :: m -> m -> m)
> }}}
>
> This came up while implementing `Applicative` for `K1` in phab:D4447.
> `K1` is essentially the same type as `Const` and thus their instances
> should be identical for the sake of consistency. But it's not clear to me
> whether `Const`'s `Applicative` instance is already optimal. Is it?

New description:

 {{{
 instance Monoid m => Applicative (Const m) where
     pure _ = Const mempty
     liftA2 _ (Const x) (Const y) = Const (x `mappend` y)
     (<*>) = coerce (mappend :: m -> m -> m)
 }}}

 https://hackage.haskell.org/package/base-4.10.1.0/docs/src/Data.Functor.Const.html#line-69


 `(<*>)` is implemented with a `coerce` but `liftA2` isn't. Would the
 following not have better inlining behavior?

 {{{
     liftA2 _ = coerce (mappend :: m -> m -> m)
 }}}

 Going further, should the unused argument also be moved to the RHS? What
 about `pure`? What are the pros and cons compared to this other
 alternative:

 {{{
     pure = \_ -> Const mempty
     liftA2 = \_ -> coerce (mappend :: m -> m -> m)
 }}}

 This came up while implementing `Applicative` for `K1` in phab:D4447. `K1`
 is essentially the same type as `Const` and thus their instances should be
 identical for the sake of consistency. But it's not clear to me whether
 `Const`'s `Applicative` instance is already optimal. Is it?

--

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14855#comment:3>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list