packages feed

tagged-th (empty) → 0.1

raw patch · 5 files changed

+173/−0 lines, 5 filesdep +basedep +taggeddep +template-haskellsetup-changed

Dependencies added: base, tagged, template-haskell, type-spine

Files

+ Data/Proxy/TH.hs view
@@ -0,0 +1,53 @@+{-# LANGUAGE TemplateHaskell, KindSignatures, ViewPatterns, EmptyDataDecls #-}++{- |++Module      :  Data.Proxy.TH+Copyright   :  (c) The University of Kansas 2011+License     :  BSD3++Maintainer  :  nicolas.frisby@gmail.com+Stability   :  experimental+Portability :  see LANGUAGE pragmas (... GHC)++Quasiquoter and TH-splice generator for proxies using @type-spine@'s @k -> *@+kind wrappers.++-}+module Data.Proxy.TH (module Data.Proxy.TH, Proxy(..)) where++import Data.Proxy.TH.Aux++import Type.Spine.Stage0 (kTypeG)++import Language.Haskell.TH+import Language.Haskell.TH.Quote++import Data.Proxy+++++qProxy :: QuasiQuoter+qProxy = QuasiQuoter (\s -> [| Proxy :: $(typ s) |])+                     pat typ (error "Data.Proxy.TH.qProxy Dec") where+  typ s = do+    (i, k) <- parseProxy_ s+    let holder = kTypeG k+    [t| Proxy ($holder $(return i)) |]+  pat s = viewP [| id :: $(typ s) -> $(typ s) |] (conP 'Proxy [])++thProxyT :: Type -> Q Type+thProxyT ty@(unAppT -> (ConT n, length -> k)) = do+  i <- reify n+  (drop k -> ks) <- case i of+    TyConI (DataD _ _ tvbs _ _) -> return $ map tvb_kind tvbs+    TyConI (NewtypeD _ _ tvbs _ _) -> return $ map tvb_kind tvbs+    PrimTyConI _ args _ -> return (replicate args StarK)+    _ -> thProxyT_fail $ Just n+  let holder = kTypeG $ foldr ArrowK StarK ks+  [t| Proxy ($holder $(return ty)) |]+thProxyT _ = thProxyT_fail Nothing++thProxy :: Type -> Q Exp+thProxy ty = [| Proxy :: $(thProxyT ty) |]
+ Data/Proxy/TH/Aux.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE ViewPatterns #-}++{- |++Module      :  Data.Proxy.TH.Aux+Copyright   :  (c) The University of Kansas 2011+License     :  BSD3++Maintainer  :  nicolas.frisby@gmail.com+Stability   :  experimental+Portability :  see LANGUAGE pragmas (... GHC)++A parser for simple type expressions, including kinds and excluding operators.++-}+module Data.Proxy.TH.Aux where++import Language.Haskell.TH++import Type.Spine.Kinds (trim, parseK)++import qualified Control.Arrow as Arrow+import Control.Monad (liftM, when, MonadPlus(..))++import Data.Char (isLower, isUpper)++instance MonadPlus Q where mzero = fail "mzero"; mplus = flip recover++tvb_kind (PlainTV _) = StarK+tvb_kind (KindedTV _ k) = k++unAppT (AppT f x) = Arrow.second (++ [x]) $ unAppT f+unAppT ty = (ty, [])++++occT n@(nameBase -> (c : _)) | startsIdent c = VarT n+                             | otherwise = ConT n+occT _ = error "occT needs a non-empty name"++--------------------+startsIdent c = isLower c || '_' == c++startsName c = isUpper c || startsIdent c++parseIdent :: MonadPlus m => String -> m ([Type], String)+parseIdent s = do+  s <- return $ trim s+  (i, s) <- return $+    break (`notElem` "_'" ++ ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9']) s+  when (null i) $ fail $ "no identifier: `" ++ s ++ "'"+  return $ ([occT $ mkName i], s)++parseParen s = ($ s) $ parseParen' . trim+parseParen' ('(' : s) = do+  (ty, trim -> s) <- parseType s+  case s of+    ')' : s -> return ([foldl1 AppT ty], s)+    _ -> fail $ "expecting `)': " ++ s+parseParen' s = fail $ "expecting `(': " ++ s++parseType s = do+  (ty, s) <- parseIdent s `mplus` parseParen s+  x <- (Just `liftM` parseType s) `mplus` return Nothing+  return $ maybe (ty, s) (Arrow.first (foldl1 AppT ty :)) x++parseProxy_ :: MonadPlus m => String -> m (Type, Kind)+parseProxy_ s = parseProxy s >>= \(x, s) -> case trim s of+  "" -> return x+  _ -> fail $ "Data.Proxy.TH.Aux.parseProxy_: " ++ s++parseProxy :: MonadPlus m => String -> m ((Type, Kind), String)+parseProxy = w . trim where+  w s@((startsName -> True) : _) = do+    (foldl1 AppT -> ty, s) <- parseType s+    case trim s of+      ':' : ':' : s -> do+        (k, s) <- parseK s+        return ((ty, k), s)+      _ -> return ((ty, StarK), s)+  w s = fail $ "Data.Proxy.TH.Aux.parseProxy: " ++ s++++--------------------+thProxyT_fail :: Maybe Name -> Q a+thProxyT_fail n = fail $ "thProxyT handles only applications of data/newtype and primitive type constructors" ++ case n of+  Just n -> "; " ++ show n ++ " is unsupported"+  Nothing -> ""
+ LICENSE view
@@ -0,0 +1,1 @@+BSD3
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ tagged-th.cabal view
@@ -0,0 +1,28 @@+name: tagged-th+version: 0.1++build-type: Simple++category: Template Haskell, Phantom Types++author: Nicolas Frisby <nicolas.frisby@gmail.com>+maintainer: Nicolas Frisby <nicolas.frisby@gmail.com>++stability: experimental++synopsis: QuasiQuoter and Template Haskell splices for creating proxies at higher-kinds++description: QuasiQuoter and Template Haskell splices for creating proxies at+  higher-kinds (via @type-spine@'s @k -> *@ kind wrappers)++license: BSD3+license-file: LICENSE++cabal-version: >= 1.6.0.1++library+  build-depends: base >= 4 && < 5, template-haskell+  build-depends: tagged >= 0.2 && < 0.3+  build-depends: type-spine < 0.2++  exposed-modules: Data.Proxy.TH, Data.Proxy.TH.Aux