Skip to content

Allow ‘unsafe’ deriving strategy, deriving code with ‘unsafeCoerce’

This

newtype M m a = M (m a)
  deriving newtype
    Functor

produces something similar to

instance Functor m => Functor (M m) where
  fmap :: forall a a'. (a -> a') -> (M m a -> M m a')
  fmap = coerce (fmap @m @a @a')

but as wiki:Roles2 points out, this fails for methods such as join_:

class MonadJoin m where
  join_ :: m (m a) -> m a

newtype M m a = M (m a)
  deriving newtype
    MonadJoin 
 -- Couldn't match representation of type ‘m (M m a)’ with that of ‘m (m a)’

I think the user should be given the option to respect the roles or not by supplying unsafe wiki:Commentary/Compiler/DerivingStrategies

newtype M m a = M (m a)
  deriving unsafe newtype
    MonadJoin

-- -( Produces `unsafeCoerce' instead of `coerce' )-

-- instance MonadJoin m => MonadJoin (M m) where
--   join_ :: forall a. M m (M m a) -> M m a
--   join_ = unsafeCoerce (join_ @m @a)

This lets us (newtype-) derive a host of instances that we currently can not: Traversable, Distributive (currently forbidden due to distribute), Trace, ProfunctorMonad / ProfunctorComonad, ...

It does not seem like lenses (FunctorWithIndex, FoldableWithIndex, TraversableWithIndex) work with this though

Trac metadata
Trac field Value
Version 8.0.1
Type FeatureRequest
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information