
#13191: Make liftA2 a method of Applicative -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: dfeuer Type: feature | Status: new request | Priority: normal | Milestone: 8.2.1 Component: Core | Version: 8.0.1 Libraries | Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): Phab:D3031 | Wiki Page: -------------------------------------+------------------------------------- Some functors support implementations of `liftA2` that are considerably faster than the usual definition. Furthermore, some people see `liftA2` as more intuitive and fundamental to the idea of `Applicative` than `<*>` is. This has been discussed on the libraries list in https://mail.haskell.org/pipermail/libraries/2017-January/027579.html and (as an official proposal) in https://mail.haskell.org/pipermail/libraries/2017-January/027612.html. All who expressed an opinion favored the proposal. One (David Menendez) specified that his support was weak. The others (Conal Elliot, Kris Nuttycombe, Wren Romano, Bardur Arantsson, and Mario Blažević) either supported the proposal strongly or merely indicated they were "+1". Conal Elliot wrote: [[BR]] [[BR]]
+1.
I also sometimes define a specialized `liftA2` and then use it to define `(<*>)`, which then gets used to define the real `liftA2`.
I think of `liftA2` as playing a role similar to `foldMap` and `traverse`, while `(<*>)` corresponds to `fold` and `sequenceA`. The first three self- compose nicely: `liftA2.liftA2.liftA2`, `foldMap.foldMap.foldMap`, and `traverse.traverse.traverse`. With functor composition, it's so much nicer to write `liftA2.liftA2` (in the style of `Functor`, `Foldable`, and `Traversable`) rather than `liftA2 (<*>)`. [[BR]]
Wren Romano wrote [[BR]] [[BR]]
I'm also all for adding liftA2 to the class and have noticed this inefficiency/asymmetry when working on the class hierarchies for other languages [[BR]]
I'm in favor of this change. From my perspecive, liftA2 is actually the fundamental Applicative operation, an <*> is merely a convenient isomorphism. When I'm teaching, showing the symmetry between the following always seems to help students:
fmap :: (a -> b) -> f a -> f b liftA2 :: (a -> b -> c) -> f a -> f b -> f c flip (>>=) :: (a -> f b) -> f a -> f b
<*> is obviously exceptionally useful in practice. But liftA2 seems like
Kris NuttyCombe wrote [[BR]] [[BR]] the
more essential shape of that operation.
-- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13191 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler