6 module Data.Collections.Newtype.TH
10 import Control.Applicative hiding (empty)
11 import Control.Monad.Unicode
12 import Data.Collections
13 import Data.Collections.BaseInstances ()
15 import Language.Haskell.TH.Lib
16 import Language.Haskell.TH.Ppr
17 import Language.Haskell.TH.Syntax
18 import Prelude hiding (concat, exp)
19 import Prelude.Unicode
21 type Deriver = Q Cxt → Q Type → Q Exp → Q Exp → Q Dec
24 derive ∷ Q [Dec] → Q [Dec]
25 derive = (concat <$>) ∘ (mapM go =≪)
28 go (InstanceD c ty _) = deriveInstance c ty
29 go _ = fail "derive: usage: derive [d| instance A; instance B; ... |]"
31 deriveInstance ∷ Cxt → Type → Q [Dec]
33 = do (wrapperTy, deriver) ← inspectInstance ty
34 (wrap , wrapD ) ← genWrap wrapperTy
35 (unwrap , unwrapD) ← genUnwrap wrapperTy
36 (: wrapD ⧺ unwrapD) <$> deriver (return c )
41 inspectInstance ∷ Type → Q (Type, Deriver)
42 inspectInstance (AppT (AppT (ConT classTy) wrapperTy) _)
43 | classTy ≡ ''Unfoldable
44 = return (wrapperTy, deriveUnfoldable)
46 = fail $ "deriveInstance: unsupported type: " ⧺ pprint ty
48 genWrap ∷ Type → Q (Exp, [Dec])
50 = do name ← newName "wrap"
51 (con, ty) ← wrapperConTy wrapperTy
53 [ sigD name [t| $(return ty) → $(return wrapperTy) |]
54 , pragInlD name (inlineSpecNoPhase True True)
55 , funD name [clause [] (normalB (conE con)) []]
57 return (VarE name, decls)
59 genUnwrap ∷ Type → Q (Exp, [Dec])
61 = do name ← newName "unwrap"
63 (con, ty) ← wrapperConTy wrapperTy
65 [ sigD name [t| $(return wrapperTy) → $(return ty) |]
66 , pragInlD name (inlineSpecNoPhase True True)
67 , funD name [clause [conP con [varP i]] (normalB (varE i)) []]
69 return (VarE name, decls)
71 wrapperConTy ∷ Type → Q (Name, Type)
72 wrapperConTy = (conTy =≪) ∘ tyInfo
74 tyInfo ∷ Type → Q Info
75 tyInfo (ConT name) = reify name
76 tyInfo (AppT ty _) = tyInfo ty
77 tyInfo (SigT ty _) = tyInfo ty
79 = fail $ "wrapperConTy: unsupported type: " ⧺ pprint ty
81 conTy ∷ Info → Q (Name, Type)
82 conTy (TyConI (NewtypeD [] _ [] (NormalC con [(NotStrict, ty)]) []))
85 = fail $ "wrapperConTy: unsupported type: " ⧺ pprint info
87 methodNames ∷ Name → Q [Name]
88 methodNames = (names =≪) ∘ reify
90 names ∷ Info → Q [Name]
91 names (ClassI (ClassD _ _ _ _ decls) _)
92 = return ∘ catMaybes $ map name decls
93 names c = fail $ "methodNames: not a class: " ⧺ pprint c
95 name ∷ Dec → Maybe Name
96 name (SigD n _) = Just n
99 pointfreeMethod ∷ (Name → Q Exp) → Name → Q Dec
100 pointfreeMethod f name
101 = funD name [clause [] (normalB (f name)) []]
103 deriveUnfoldable ∷ Q Cxt → Q Type → Q Exp → Q Exp → Q Dec
104 deriveUnfoldable c ty wrap unwrap
105 = do names ← methodNames ''Unfoldable
106 instanceD c ty $ pointfreeMethod exp <$> names
111 = [| ($wrap ∘) ∘ (∘ $unwrap) ∘ insert |]
115 = [| $wrap ∘ singleton |]
117 = [| ($wrap ∘) ∘ (∘ $unwrap) ∘ insertMany |]
118 | name ≡ 'insertManySorted
119 = [| ($wrap ∘) ∘ (∘ $unwrap) ∘ insertManySorted |]
121 = fail $ "deriveUnfoldable: unknown method: " ⧺ pprint name
124 instance Unfoldable MIMEParams (CIAscii, Text) where
125 {-# INLINE insert #-}
126 insert p (MIMEParams m)
127 = MIMEParams $ insert p m
131 {-# INLINE singleton #-}
133 = MIMEParams $ singleton p
134 {-# INLINE insertMany #-}
135 insertMany f (MIMEParams m)
136 = MIMEParams $ insertMany f m
137 {-# INLINE insertManySorted #-}
138 insertManySorted f (MIMEParams m)
139 = MIMEParams $ insertManySorted f m