Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,874
    • Issues 4,874
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 457
    • Merge requests 457
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #19713
Closed
Open
Created Apr 16, 2021 by Icelandjack@IcelandjackReporter

DeriveFunctor: Use `contramap' in contravariant position

This rule for cofmap in GHC.Tc.Deriv.Functor can not deal with a type variable in contravariant position

  $(cofmap 'a 'b x)          = x     -- when b does not contain a
  $(cofmap 'a 'a x)          = error "type variable in contravariant position"
  $(cofmap 'a '(b1,b2) x)    = case x of (x1,x2) -> ($(cofmap 'a 'b1) x1, $(cofmap 'a 'b2) x2)
  $(cofmap 'a '(T b1 a) x)   = error "type variable in contravariant position" -- when a only occurs directly as the last argument of T
  $(cofmap 'a '(T b1 b2) x)  = fmap (\y. $(cofmap 'a 'b2 y)) x -- when a only occurs in the last parameter, b2
  $(cofmap 'a '(tb -> tc) x) = \(y:tb[b/a]) -> $(cofmap 'a' 'tc' (x $(fmap 'a 'tb y)))

but now that we have Data.Functor.Contravariant in base why not generate an invocation to contramap?

  $(cofmap 'a '(T b1 a) x) = contramap f x

As an example, this works becuase of the special case for functions

> :set -XDerivingStrategies -XDeriveFunctor
> newtype F a = MkF ((a -> Int) -> Int) deriving stock Functor

but if we use Op Int a (which is a newtype wrapping a -> Int) ghc does not know how to derive it.

> newtype F a = MkF (Op Int a -> Int) deriving stock Functor

<interactive>:10:52: error:
    • Can't make a derived instance of
        ‘Functor F’ with the stock strategy:
        Constructor ‘MkF’ must not use the type variable in a function argument
    • In the newtype declaration for ‘F’

I claim it should work by inserting a contramap invocation there so both these definitions

newtype F a = MkF (Op Int      a -> Int) deriving stock Functor
newtype F a = MkF (Equivalence a -> Int) deriving stock Functor

would generate the following (basically)

instance Functor F where
  fmap :: (a -> a') -> (F a -> F a')
  fmap f (MkF as) = MkF (fmap as (contramap f))
Edited Apr 16, 2021 by Icelandjack
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking