Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Draft: Use withDict to implement reify
Browse files Browse the repository at this point in the history
This implements one half of #44. See
https://gitlab.haskell.org/ghc/ghc/-/issues/21568.
RyanGlScott committed Mar 15, 2024
1 parent a9443f4 commit 4ac76d6
Showing 2 changed files with 29 additions and 6 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.markdown
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# next [????.??.??]
* Implement `reify` in terms of the `withDict` primitive instead of
`unsafeCoerce` on GHC 9.4 or later. See
[#44](https://github.com/ekmett/reflection/issues/44) for the motivation
behind this change.

# 2.1.7 [2023.02.28]
* When building with `base-4.18` (GHC 9.6) or later, implement `reifyNat` and
`reifySymbol` using the API provided by `GHC.TypeLits` instead of resorting
29 changes: 23 additions & 6 deletions fast/Data/Reflection.hs
Original file line number Diff line number Diff line change
@@ -21,6 +21,11 @@
# else
{-# LANGUAGE TemplateHaskell #-}
# endif

# if MIN_VERSION_base(4,17,0)
{-# LANGUAGE ImpredicativeTypes #-}
{-# LANGUAGE TypeApplications #-}
# endif
#endif

{-# LANGUAGE TypeFamilies #-}
@@ -151,16 +156,22 @@ import Language.Haskell.TH hiding (reify)

import System.IO.Unsafe

#ifndef __HUGS__
import Unsafe.Coerce
#endif

#if MIN_VERSION_base(4,7,0)
import Data.Coerce (Coercible, coerce)
#endif

#if MIN_VERSION_base(4,17,0)
import qualified Data.Kind as K (Type)
import qualified GHC.Exts as Exts (Any)
import GHC.Exts (withDict)
#endif

#if MIN_VERSION_base(4,18,0)
import qualified GHC.TypeNats as TN
#else
# ifndef __HUGS__
import Unsafe.Coerce
# endif
#endif

-- Due to https://gitlab.haskell.org/ghc/ghc/issues/16893, inlining
@@ -183,11 +194,17 @@ class Reifies s a | s -> a where
-- reified type.
reflect :: proxy s -> a

newtype Magic a r = Magic (forall (s :: *). Reifies s a => Proxy s -> r)

-- | Reify a value at the type level, to be recovered with 'reflect'.
reify :: forall a r. a -> (forall (s :: *). Reifies s a => Proxy s -> r) -> r
#if MIN_VERSION_base(4,17,0)
reify a k = withDict @(Reifies (Exts.Any @K.Type) a)
@(forall (proxy :: K.Type -> K.Type). proxy Exts.Any -> a)
(const a) (k @Exts.Any) Proxy
#else
reify a k = unsafeCoerce (Magic k :: Magic a r) (const a) Proxy

newtype Magic a r = Magic (forall (s :: *). Reifies s a => Proxy s -> r)
#endif
{-# INLINE_UNSAFE_COERCE reify #-}

#if __GLASGOW_HASKELL__ >= 707

0 comments on commit 4ac76d6

Please sign in to comment.