[GHC] #14292: Coercing between constraints of newtypes
GHC
ghc-devs at haskell.org
Wed Sep 27 18:03:59 UTC 2017
#14292: Coercing between constraints of newtypes
-------------------------------------+-------------------------------------
Reporter: Iceland_jack | Owner: (none)
Type: feature request | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.2.1
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by RyanGlScott):
I wouldn't say that this is rejected due to a fundamental limitation so
much as a deliberate design choice. The immediate reason that the former
program is rejected is due to roles. By default, all class parameters are
given role `nominal`, so you can't coerce between `Num a` and `Num b`
unless `a ~ b`.
Why is the case? Even if `a` and `b` are representationally equal, there's
absolutely no guarantee that their corresponding `Num` dictionaries are
also representationally equal. After all, a `Num` instance for `USD` might
do something crazy like `fromInteger _ = USD 42`. Defaulting class
parameters to `nominal` is thus a conservative way to avoid the
shenanigans that would unfold if you treated a `Num USD` dictionary as a
`Num Int` one, or vice versa.
Now you might object: "But I'm a careful programmer! I promise to only use
`Num Int` and `Num USD` dictionaries that are representationally
equivalent!" In that case, there is a fallback mechanism in the form of
`IncoherentInstances`:
{{{#!hs
{-# Language ConstraintKinds #-}
{-# Language GADTs #-}
{-# Language IncoherentInstances #-}
{-# Language RoleAnnotations #-}
import Data.Coerce
import Prelude hiding (Num(..))
newtype USD = USD Int
data Dict c where
Dict :: c => Dict c
type role Num representational
class Num a where
-- ...
instance Num Int
instance Num USD
num :: Dict (Num Int) -> Dict (Num USD)
num = coerce
}}}
I hope it should be obvious from the name `IncoherentInstances` alone that
this fallback carries significant risks. Use this trick at your own
discretion.
Does that answer the question satisfactorily? If so, please feel free to
close the ticket.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14292#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list