Skip to content

Commit

Permalink
Use withDict to implement bindIP on recent GHCs
Browse files Browse the repository at this point in the history
Instead of `unsafeCoerce`, we can use the more recent `withDict` primitive
from `GHC.Exts`. Among other benefits, this is more likely to be future-proof
against possible changes to GHC's representation of "newtype classes" in the
future.

Fixes #165.
  • Loading branch information
RyanGlScott committed May 14, 2022
1 parent d87ea56 commit 4625251
Showing 1 changed file with 12 additions and 3 deletions.
15 changes: 12 additions & 3 deletions Language/Haskell/TH/Desugar/Util.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ import Data.Generics hiding ( Fixity )
import Data.Traversable
import Data.Maybe
import GHC.Classes ( IP )

#if MIN_VERSION_base(4,17,0)
import GHC.Exts ( withDict )
#else
import Unsafe.Coerce ( unsafeCoerce )
#endif

----------------------------------------
-- TH manipulations
Expand Down Expand Up @@ -423,16 +428,20 @@ extractBoundNamesPat (UnboxedSumP pat _ _) = extractBoundNamesPat pat
-- General utility
----------------------------------------

-- dirty implementation of explicit-to-implicit conversion
newtype MagicIP name a r = MagicIP (IP name a => r)

-- | Get an implicit param constraint (@IP name a@, which is the desugared
-- form of @(?name :: a)@) from an explicit value.
--
-- This function is only available with GHC 8.0 or later.
bindIP :: forall name a r. a -> (IP name a => r) -> r
#if MIN_VERSION_base(4,17,0)
bindIP = withDict @a @(IP name a)
#else
bindIP val k = (unsafeCoerce (MagicIP @name k) :: a -> r) val

-- dirty implementation of explicit-to-implicit conversion
newtype MagicIP name a r = MagicIP (IP name a => r)
#endif

-- like GHC's
splitAtList :: [a] -> [b] -> ([b], [b])
splitAtList [] x = ([], x)
Expand Down

0 comments on commit 4625251

Please sign in to comment.