@@ -10,13 +10,11 @@
11module Streamly.Internal.Data.Unbox.TH
11module Streamly.Internal.Data.Unbox.TH
12 ( deriveUnbox
12 ( deriveUnbox
15 -- th-helpers
14 -- th-helpers
16 , DataCon(..)
15 , DataCon(..)
17 , DataType(..)
16 , DataType(..)
18 , reifyDataType
17 , reifyDataType
22--------------------------------------------------------------------------------
20--------------------------------------------------------------------------------
@@ -69,10 +67,6 @@ tvName = elimTV id (\n _ -> n)
69tyVarBndrName :: TyVarBndr_ flag -> Name
67tyVarBndrName :: TyVarBndr_ flag -> Name
70tyVarBndrName = tvName
68tyVarBndrName = tvName
72−appsT :: Type -> [Type] -> Type
74−appsT x (y:xs) = appsT (AppT x y) xs
76-- | Simplified info about a 'DataD'. Omits deriving, strictness,
70-- | Simplified info about a 'DataD'. Omits deriving, strictness,
77-- kind info, and whether it's @data@ or @newtype@.
71-- kind info, and whether it's @data@ or @newtype@.
78data DataType = DataType
72data DataType = DataType
@@ -397,8 +391,8 @@ mkPokeExpr headTy cons =
397-- [(Nothing, (ConT ''Bool)), (Nothing, (VarT (mkName "b")))]
391-- [(Nothing, (ConT ''Bool)), (Nothing, (VarT (mkName "b")))]
400−deriveUnboxInternal :: Cxt -> Type -> [DataCon] -> Q [Dec]
394+deriveUnboxInternal :: Type -> [DataCon] -> ([Dec] -> Q [Dec]) -> Q [Dec]
401−deriveUnboxInternal preds headTy cons = do
395+deriveUnboxInternal headTy cons mkDec = do
402 sizeOfMethod <- mkSizeOfExpr headTy cons
396 sizeOfMethod <- mkSizeOfExpr headTy cons
403 peekMethod <- mkPeekExpr headTy cons
397 peekMethod <- mkPeekExpr headTy cons
404 pokeMethod <- mkPokeExpr headTy cons
398 pokeMethod <- mkPokeExpr headTy cons
@@ -428,77 +422,54 @@ deriveUnboxInternal preds headTy cons = do
431− return [InstanceD Nothing preds (AppT (ConT ''Unbox) headTy) methods]
425+ mkDec methods
433−-- | @deriveUnbox dataTypeName@ generates a template Haskell splice consisting
427+-- | Given an 'Unbox' instance declaration splice without the methods,
434−-- of a declaration of the 'Unbox' instance for the given dataTypeName, all type
428+-- generate a full instance declaration including all the type class methods.
435−-- parameters of dataTypeName are required to have the 'Unbox' constraint.
440−-- data CustomDataType a b c = ...
441−-- \$(deriveUnbox ''CustomDataType)
444−-- Generates the following code:
430+-- Usage:
447−-- instance (Unbox a, Unbox b, Unbox c) => Unbox (CustomDataType a b c) where
433+-- \$(deriveUnbox [d|instance Unbox a => Unbox (Maybe a)|])
451−-- To control which type parameters get the Unbox constraint, use
452−-- 'deriveUnboxWith'.
453−deriveUnbox :: Name -> Q [Dec]
435+deriveUnbox :: Q [Dec] -> Q [Dec]
454−deriveUnbox name = do
436+deriveUnbox mDecs = do
439+ [InstanceD mo preds headTyWC []] -> do
440+ let headTy = unwrap dec headTyWC
455− dt <- reifyDataType name
441+ dt <- reifyDataType (getMainTypeName dec headTy)
456− let preds = map (unboxPred . VarT) (dtTvs dt)
457− headTy = appsT (ConT name) (map VarT (dtTvs dt))
458− cons = dtCons dt
442+ let cons = dtCons dt
459− deriveUnboxInternal preds headTy cons
443+ deriveUnboxInternal headTy cons (mkInst mo preds headTyWC)
444+ _ -> errorMessage dec
463− unboxPred ty =
448+ mkInst mo preds headTyWC methods =
464−#if MIN_VERSION_template_haskell(2,10,0)
449+ pure [InstanceD mo preds headTyWC methods]
465− AppT (ConT ''Unbox) ty
450+
466−#else
451+ errorMessage dec =
467− ClassP ''Unbox [ty]
452+ error $ unlines
468−#endif
453+ [ "Error: deriveUnbox:"
455+ , ">> " ++ pprint dec
457+ , "The supplied declaration not a valid instance declaration."
458+ , "Provide a valid Haskell instance declaration without a body."
461+ , "instance Unbox (Proxy a)"
462+ , "instance Unbox a => Unbox (Identity a)"
463+ , "instance Unbox (TableT Identity)"
470−-- | @deriveUnbox dataTypeName@ generates a template Haskell splice consisting
466+ unwrap _ (AppT (ConT _) r) = r
471−-- of a declaration of the 'Unbox' instance for the given dataTypeName,
467+ unwrap dec _ = errorMessage dec
472−-- varNames is a list of parameter names of dataTypeName that are required
473−-- to have the 'Unbox' constraint.
478−-- data CustomDataType a b c = ...
479−-- \$(deriveUnboxWith ["a", "c"] ''CustomDataType)
482−-- Generates the following code:
485−-- instance (Unbox a, Unbox c) => Unbox (CustomDataType a b c) where
489−deriveUnboxWith :: [String] -> Name -> Q [Dec]
490−deriveUnboxWith vars name = do
491− dt <- reifyDataType name
492− let preds = map (unboxPred . VarT) (fmap mkName vars)
493− headTy = appsT (ConT name) (map VarT (dtTvs dt))
495− deriveUnboxInternal preds headTy cons
497− where
469+ getMainTypeName dec = go
499− unboxPred ty =
471+ where
500−#if MIN_VERSION_template_haskell(2,10,0)
472+
501− AppT (ConT ''Unbox) ty
473+ go (ConT nm) = nm
502−#else
474+ go (AppT l _) = go l
503− ClassP ''Unbox [ty]
475+ go _ = errorMessage dec