Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
GHC
GHC
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,391
    • Issues 4,391
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
    • Iterations
  • Merge Requests 371
    • Merge Requests 371
  • Requirements
    • Requirements
    • List
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Operations
    • Operations
    • Incidents
    • Environments
  • Analytics
    • Analytics
    • CI / CD
    • Code Review
    • Insights
    • Issue
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #13191

Closed
Open
Opened Jan 27, 2017 by David Feuer@treeowlReporter

Make liftA2 a method of Applicative

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 Elliott, Kris Nuttycombe, Wren Romano, Bardur Arantsson, and Mario Blažević) either supported the proposal strongly or merely indicated they were "+1". Conal Elliott 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]]

Kris NuttyCombe wrote [[BR]] [[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 the more essential shape of that operation.

Edited Mar 10, 2019 by conal
Assignee
Assign to
8.2.1
Milestone
8.2.1 (Past due)
Assign milestone
Time tracking
None
Due date
None
Reference: ghc/ghc#13191