Skip to content

Commit a59b625

Browse files
committed
Simplify reifyTypeable
At least, when we use `TypeLits`. Is there some reason we don't always?
1 parent 239a6fa commit a59b625

File tree

1 file changed

+38
-17
lines changed

1 file changed

+38
-17
lines changed

fast/Data/Reflection.hs

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,44 @@ subProxy _ _ = error "Exp.(-): undefined"
432432
-- * Typeable Reflection
433433
--------------------------------------------------------------------------------
434434

435+
stablePtrToIntPtr :: StablePtr a -> IntPtr
436+
stablePtrToIntPtr = ptrToIntPtr . castStablePtrToPtr
437+
{-# INLINE stablePtrToIntPtr #-}
438+
439+
intPtrToStablePtr :: IntPtr -> StablePtr a
440+
intPtrToStablePtr = castPtrToStablePtr . intPtrToPtr
441+
{-# INLINE intPtrToStablePtr #-}
442+
443+
argument :: (p s -> r) -> Proxy s
444+
argument _ = Proxy
445+
446+
-- This had to be moved to the top level, due to an apparent bug in
447+
-- the ghc inliner introduced in ghc 7.0.x
448+
reflectBefore :: forall (proxy :: * -> *) s b. (Proxy s -> b) -> proxy s -> b
449+
reflectBefore f = const $! f Proxy
450+
{-# NOINLINE reflectBefore #-}
451+
435452

453+
#if USE_TYPE_LITS
454+
reifyTypeable :: {- Typeable a => -} a -> (forall (s :: *). (Typeable s, Reifies s a) => Proxy s -> r) -> r
455+
# if MIN_VERSION_base(4,4,0)
456+
reifyTypeable (a :: a) k = unsafeDupablePerformIO $ do
457+
# else
458+
reifyTypeable (a :: a) k = unsafePerformIO $ do
459+
# endif
460+
p <- newStablePtr a
461+
let n = stablePtrToIntPtr p
462+
reifyNat (fromIntegral n) (\(_ :: Proxy n) ->
463+
reflectBefore (fmap return k) $
464+
(Proxy :: Proxy (Stable n a)))
465+
data Stable (n :: Nat) a
466+
instance KnownNat n => Reifies (Stable n a) a where
467+
reflect = r where
468+
r = unsafePerformIO $ const <$> deRefStablePtr p <* freeStablePtr p
469+
s = argument r
470+
p = intPtrToStablePtr $ fromIntegral $ reflect (Proxy :: Proxy n)
471+
472+
#else
436473
class Typeable s => B s where
437474
reflectByte :: proxy s -> IntPtr
438475

@@ -492,14 +529,6 @@ stable :: p b0 -> p b1 -> p b2 -> p b3 -> p b4 -> p b5 -> p b6 -> p b7
492529
stable _ _ _ _ _ _ _ _ = Proxy
493530
{-# INLINE stable #-}
494531

495-
stablePtrToIntPtr :: StablePtr a -> IntPtr
496-
stablePtrToIntPtr = ptrToIntPtr . castStablePtrToPtr
497-
{-# INLINE stablePtrToIntPtr #-}
498-
499-
intPtrToStablePtr :: IntPtr -> StablePtr a
500-
intPtrToStablePtr = castPtrToStablePtr . intPtrToPtr
501-
{-# INLINE intPtrToStablePtr #-}
502-
503532
byte0 :: p (Stable (W b0 b1 b2 b3) w1 a) -> Proxy b0
504533
byte0 _ = Proxy
505534

@@ -524,9 +553,6 @@ byte6 _ = Proxy
524553
byte7 :: p (Stable w0 (W b4 b5 b6 b7) a) -> Proxy b7
525554
byte7 _ = Proxy
526555

527-
argument :: (p s -> r) -> Proxy s
528-
argument _ = Proxy
529-
530556
instance (B b0, B b1, B b2, B b3, B b4, B b5, B b6, B b7, w0 ~ W b0 b1 b2 b3, w1 ~ W b4 b5 b6 b7)
531557
=> Reifies (Stable w0 w1 a) a where
532558
reflect = r where
@@ -543,12 +569,6 @@ instance (B b0, B b1, B b2, B b3, B b4, B b5, B b6, B b7, w0 ~ W b0 b1 b2 b3, w1
543569
(reflectByte (byte7 s) `shiftL` 56)
544570
{-# NOINLINE reflect #-}
545571

546-
-- This had to be moved to the top level, due to an apparent bug in
547-
-- the ghc inliner introduced in ghc 7.0.x
548-
reflectBefore :: forall (proxy :: * -> *) s b. (Proxy s -> b) -> proxy s -> b
549-
reflectBefore f = const $! f Proxy
550-
{-# NOINLINE reflectBefore #-}
551-
552572
-- | Reify a value at the type level in a 'Typeable'-compatible fashion, to be recovered with 'reflect'.
553573
--
554574
-- This can be necessary to work around the changes to @Data.Typeable@ in GHC HEAD.
@@ -570,6 +590,7 @@ reifyTypeable a k = unsafePerformIO $ do
570590
reifyByte (fromIntegral (n `shiftR` 56)) (\s7 ->
571591
reflectBefore (fmap return k) $
572592
stable s0 s1 s2 s3 s4 s5 s6 s7))))))))
593+
#endif
573594

574595

575596
data ReifiedMonoid a = ReifiedMonoid { reifiedMappend :: a -> a -> a, reifiedMempty :: a }

0 commit comments

Comments
 (0)