From: PHO Date: Thu, 17 Nov 2011 16:11:24 +0000 (+0900) Subject: auto-derive Foldable X-Git-Url: http://git.cielonegro.org/gitweb.cgi?a=commitdiff_plain;h=b8d4661;p=Lucu.git auto-derive Foldable Ditz-issue: e0312227f40a0fa92d4c5d69a64dad473f54389a --- diff --git a/Data/Collections/Newtype/TH.hs b/Data/Collections/Newtype/TH.hs index c5393bb..d81cb01 100644 --- a/Data/Collections/Newtype/TH.hs +++ b/Data/Collections/Newtype/TH.hs @@ -11,11 +11,15 @@ import Control.Applicative hiding (empty) import Control.Monad.Unicode import Data.Collections import Data.Collections.BaseInstances () +import Data.Data +import Data.Generics.Aliases +import Data.Generics.Schemes import Data.Maybe import Language.Haskell.TH.Lib import Language.Haskell.TH.Ppr import Language.Haskell.TH.Syntax -import Prelude hiding (concat, exp) +import Prelude hiding ( concat, concatMap, exp + , foldl, foldr, foldl1, foldr1, null) import Prelude.Unicode type Deriver = Q Cxt → Q Type → Q Exp → Q Exp → Q Dec @@ -33,15 +37,23 @@ deriveInstance c ty = do (wrapperTy, deriver) ← inspectInstance ty (wrap , wrapD ) ← genWrap wrapperTy (unwrap , unwrapD) ← genUnwrap wrapperTy - (: wrapD ⧺ unwrapD) <$> deriver (return c ) - (return ty ) - (return wrap ) - (return unwrap) + instanceDecl ← deriver (return c ) + (return ty ) + (return wrap ) + (return unwrap) + return $ [ d | d ← wrapD , wrap `isUsedIn` instanceDecl ] + ⧺ [ d | d ← unwrapD, unwrap `isUsedIn` instanceDecl ] + ⧺ [ instanceDecl ] + +isUsedIn ∷ (Eq α, Typeable α, Data β) ⇒ α → β → Bool +isUsedIn α = (> 0) ∘ gcount (mkQ False (≡ α)) inspectInstance ∷ Type → Q (Type, Deriver) inspectInstance (AppT (AppT (ConT classTy) wrapperTy) _) | classTy ≡ ''Unfoldable = return (wrapperTy, deriveUnfoldable) + | classTy ≡ ''Foldable + = return (wrapperTy, deriveFoldable) inspectInstance ty = fail $ "deriveInstance: unsupported type: " ⧺ pprint ty @@ -96,14 +108,18 @@ methodNames = (names =≪) ∘ reify name (SigD n _) = Just n name _ = Nothing -pointfreeMethod ∷ (Name → Q Exp) → Name → Q Dec +pointfreeMethod ∷ (Name → Q Exp) → Name → [Q Dec] pointfreeMethod f name - = funD name [clause [] (normalB (f name)) []] + = [ funD name [clause [] (normalB (f name)) []] + -- THINKME: Inserting PragmaD in an InstanceD causes an error + -- least GHC 7.0.3. Why? + -- , pragInlD name (inlineSpecNoPhase True False) + ] deriveUnfoldable ∷ Q Cxt → Q Type → Q Exp → Q Exp → Q Dec deriveUnfoldable c ty wrap unwrap = do names ← methodNames ''Unfoldable - instanceD c ty $ pointfreeMethod exp <$> names + instanceD c ty $ concatMap (pointfreeMethod exp) names where exp ∷ Name → Q Exp exp name @@ -120,21 +136,30 @@ deriveUnfoldable c ty wrap unwrap | otherwise = fail $ "deriveUnfoldable: unknown method: " ⧺ pprint name -{- -instance Unfoldable MIMEParams (CIAscii, Text) where - {-# INLINE insert #-} - insert p (MIMEParams m) - = MIMEParams $ insert p m - {-# INLINE empty #-} - empty - = MIMEParams empty - {-# INLINE singleton #-} - singleton p - = MIMEParams $ singleton p - {-# INLINE insertMany #-} - insertMany f (MIMEParams m) - = MIMEParams $ insertMany f m - {-# INLINE insertManySorted #-} - insertManySorted f (MIMEParams m) - = MIMEParams $ insertManySorted f m --} +deriveFoldable ∷ Q Cxt → Q Type → Q Exp → Q Exp → Q Dec +deriveFoldable c ty _ unwrap + = do names ← methodNames ''Foldable + instanceD c ty $ concatMap (pointfreeMethod exp) names + where + exp ∷ Name → Q Exp + exp name + | name ≡ 'fold + = [| fold ∘ $unwrap |] + | name ≡ 'foldMap + = [| (∘ $unwrap) ∘ foldMap |] + | name ≡ 'foldr + = [| flip flip $unwrap ∘ ((∘) ∘) ∘ foldr |] + | name ≡ 'foldl + = [| flip flip $unwrap ∘ ((∘) ∘) ∘ foldl |] + | name ≡ 'foldr1 + = [| (∘ $unwrap) ∘ foldr1 |] + | name ≡ 'foldl1 + = [| (∘ $unwrap) ∘ foldl1 |] + | name ≡ 'null + = [| null ∘ $unwrap |] + | name ≡ 'size + = [| size ∘ $unwrap |] + | name ≡ 'isSingleton + = [| isSingleton ∘ $unwrap |] + | otherwise + = fail $ "deriveFoldable: unknown method: " ⧺ pprint name diff --git a/Network/HTTP/Lucu/MIMEParams.hs b/Network/HTTP/Lucu/MIMEParams.hs index 1304c23..183a4c0 100644 --- a/Network/HTTP/Lucu/MIMEParams.hs +++ b/Network/HTTP/Lucu/MIMEParams.hs @@ -58,17 +58,9 @@ newtype MIMEParams deriving (Eq, Show, Read, Monoid, Typeable) C.derive [d| instance Unfoldable MIMEParams (CIAscii, Text) + instance Foldable MIMEParams (CIAscii, Text) |] --- FIXME: auto-derive -instance Foldable MIMEParams (CIAscii, Text) where - {-# INLINE null #-} - null (MIMEParams m) = null m - {-# INLINE size #-} - size (MIMEParams m) = size m - {-# INLINE foldr #-} - foldr f b (MIMEParams m) = foldr f b m - -- FIXME: auto-derive instance Collection MIMEParams (CIAscii, Text) where {-# INLINE filter #-}