Template Haskell - Typed Meta
Transkrypt
Template Haskell - Typed Meta
Template Haskell Typed Meta-Programming Maciej Kotowicz Wrocław, 14 grudnia 2010 Wprowadzenie Opis Template Haskell rozszerzenie do ghc, pozwalajace na meta-programowanie, rozwiazywane podczas kompilacji Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 2 / 20 Wprowadzenie Opis Template Haskell rozszerzenie do ghc, pozwalajace na meta-programowanie, rozwiazywane podczas kompilacji Quasi Quotation Pozwala na uzwania dowolnej skladni do konstrukcji programow w meta-jezyku(Haskell) Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 2 / 20 Wprowadzenie Opis You Could Have Invented MonˆHˆHˆH Macros Zastanówmy się czym są makra i jak je wprowadzić do języka Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 3 / 20 Wprowadzenie Skladnia Podstawowe konstrukcje -XTemplateHaskell albo odpowiednia pragma $(. . .) :: . . . ’e :: Name – dla wyrazen ”t :: Name – dla typow ’map ⇒ GHC.Base.map ”Maybe ⇒ Data.Maybe.Maybe Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 4 / 20 Wprowadzenie Skladnia Podstawowe konstrukcje -XTemplateHaskell albo odpowiednia pragma $(. . .) :: . . . ’e :: Name – dla wyrazen ”t :: Name – dla typow ’map ⇒ GHC.Base.map ”Maybe ⇒ Data.Maybe.Maybe Quasi-Qoutery [e|. . .|] :: Q Exp ≡ ExpQ [d|. . .|] :: Q Dec ≡ DecQ [t|. . .|] :: Q Type ≡ TypeQ – since ghc7 [p|. . .|] :: Q Pat ≡ PatQ Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 4 / 20 Printf Oleg way data Format = FLit String | FStr | FInt | FFloat deriving Show sprintf :: Args a ⇒ String → a sprintf = pr [ ] ◦ convert where convert str = case break (≡ ’%’) str of (s1 , "") → makeLit s1 (s1 , ’%’ : x : rest) | Just fd ← lookup x map → makeLit s1 ++ fd : con + take 2 s2 ( , s2 ) → error $ "bad descriptor: " + where makeLit "" = [ ] makeLit s = [FLit s ] map = [(’s’, FStr ), (’d’, FInt), (’f’, FFloat)] Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 5 / 20 Printf Oleg way class Show a ⇒ IsAllowed a instance IsAllowed Int instance IsAllowed String instance IsAllowed Float class Args a where pr :: [String ] → [Format ] → a instance Args String where pr acc desc = concat ◦ reverse $ foldl f acc desc where f acc (FLit s) = s : acc f acc = error "Brakuje argumentow" Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 6 / 20 Printf Oleg way instance (IsAllowed a, Args r ) ⇒ Args (a → r ) where pr acc desc x = uncurry pr $ fmtx desc acc where fmtx [ ] acc = error "No formatting directive for the argum fmtx (FLit s : desc) acc = fmtx desc (s : acc) fmtx (FFloat : desc) acc = (show x : acc, desc) fmtx (FInt : desc) acc = (show x : acc, desc) fmtx (FStr : desc) acc = (unq (show x) : acc, desc) unq (’"’ : str ) | last str ≡ ’"’ = init str unsq str = str test :: String test = sprintf "a[%d] := %d" (4 :: Int) (5 :: Int) Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 7 / 20 Printf TH way prTh :: String → ExpQ prTh s = gen (convert s) (lift "") where gen [ ] acc = acc gen (FInt : xs) acc = [| λn → $(gen xs [| $acc ++ show n |]) |] gen (FFloat : xs) acc = [| λg → $(gen xs [| $acc ++ show g |]) |] gen (FStr : xs) acc = [| λs → $(gen xs [| $acc ++ s |]) |] gen (FLit s : xs) acc = gen xs $ [| (+ +) |] ‘appE ‘ acc ‘appE ‘ lift s test2 = $(prTh "a[%d] := %d") 4 5 Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 8 / 20 TH implementacja monada Q newtype Q a = Q {runQ :: ∀m :: ∗ → ∗.Quasi m ⇒ m a} class (Functor m, Monad m) ⇒ Quasi m where qNewName :: String → m Name qReport :: Bool → String → m () qRecover :: m a → m a → m a qReify :: Name → m Info qLocation :: m Loc qRunIO :: IO a → m a instance Quasi IO where ... instance Quasi Q where ... Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 9 / 20 TH implementacja monada Q newtype Q a = Q {runQ :: ∀m :: ∗ → ∗.Quasi m ⇒ m a} class (Functor m, Monad m) ⇒ Quasi m where qNewName :: String → m Name qReport :: Bool → String → m () qRecover :: m a → m a → m a qReify :: Name → m Info qLocation :: m Loc qRunIO :: IO a → m a instance Quasi IO where ... instance Quasi Q where ... instance Quasi TcM where ... Co to za dziwny typ TcM? Odpowiedz kryje sie w ghc-api, jest to monada ktora odpowiada za type-checking dzieki niej mamy info z reify itp Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 9 / 20 TH implementacja Quasi Quoting data QuasiQuoter = QuasiQuoter {quoteExp :: String → Q Exp, quotePat :: String → Q Pat } class Lift t where lift :: t → Q Exp odpowiedni qoute* odpalany jest w w zaleznosci gdzie quasi-quotation wystepuje w odpowiednio wyrazeniach czy wzorcach (w ghc7 takze w typach i deklaracjach) Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 10 / 20 TH implementacja Quasi Quoting data Expr = IntVal Integer | AIntVal String | BinOp Op Expr Expr | AExp String deriving Show data Op = Mult | Plus deriving Show Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 11 / 20 TH implementacja Quasi Quoting instance Lift Expr where lift (IntVal i) = [| IntVal |] ‘appE ‘ lift i lift (AIntVal s) = [| IntVal |] ‘appE ‘ (varE $ mkName s) lift (BinOp o e1 e2 ) = mkExp [conE (mkName "BinOp"), lift o, lift e1 lift (AExp s) = varE $ mkName s -- lift e = [e] instance Lift Op where lift Mult = [| Mult |] lift Plus = [| Plus |] mkExp = foldl1 appE Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 12 / 20 TH implementacja Quasi Quoting class LiftPat t where liftPat :: t → PatQ instance LiftPat Expr where liftPat (IntVal i) = conP (mkName "IntVal") [litP $ integerL i ] liftPat (BinOp op e1 e2 ) = conP (mkName "BinOp") [liftPat op, liftP liftPat (AIntVal s) = conP (mkName "IntVal") [varP $ mkName s ] liftPat (AExp s) = varP $ mkName s instance LiftPat Op where liftPat Mult = conP (mkName "Mult") [ ] liftPat Plus = conP (mkName "Plus") [ ] Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 13 / 20 TH implementacja Quasi Quoting parseExpr = ... qqExpr = QuasiQuoter qExprExp qExprPat where qExprPat = liftPat ◦ parseExpr qExprExp = lift ◦ parseExpr eval eval eval eval :: Expr → Integer [exp |$ int : i ] = i [exp |$ x + $y ] = eval x + eval y [exp |$ x ∗ $y ] = eval x + eval y Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 14 / 20 Typowanie Idea Wg tytułu TH pozwlają na typowowane meta-programowanie, ale gdzie te typy? Jak wiemy splicowac można (będzie) wartosci o typie {Exp,Pat,Type,Dec}Q ale to nam nic nie mowi o typie wyrazenia jakie generujemy Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 15 / 20 Typowanie Idea Wg tytułu TH pozwlają na typowowane meta-programowanie, ale gdzie te typy? Jak wiemy splicowac można (będzie) wartosci o typie {Exp,Pat,Type,Dec}Q ale to nam nic nie mowi o typie wyrazenia jakie generujemy Wykonanie kodu TH jest 4 fazowe: 1 Sprawdzenie typów wyrazen pod J. . .K z tym że wyrażenion $e nadajemy typ ∀a.a 2-3 magia wynikajaca z wykonania splicow/qoutow/etc 4 Sprawdzenie typów całego modułu wraz z wygenerowanym kodem Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 15 / 20 Typowanie Problemy Too Week Tak jak mówiłem splicy mają typ ExpQ, a to nic nie mówi o tym jaki kod zostanie wygenerowany foo :: QExp → QExp foo xs = [| sum $ map lenght $ xs |] Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 16 / 20 Typowanie Problemy Too Week Tak jak mówiłem splicy mają typ ExpQ, a to nic nie mówi o tym jaki kod zostanie wygenerowany foo :: QExp → QExp foo xs = [| sum $ map lenght $ xs |] Too Strong foo :: TypeQ → Q [Dec ] foo t = [d | data T = MkT $ t; g (MkT k) = ...k... |] Jaki typ ma mieć g? Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 16 / 20 Reifikacja Info Przypomnienie class (Functor m, Monad m) ⇒ Quasi m where ... qReify :: Name → m Info ... reify :: Name → Q Info reify = Q ◦ qReify Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 17 / 20 Reifikacja Info data Info = ClassI Dec | ClassOpI Name Type Name Fixity | TyConI Dec | PrimTyConI Name Int Bool | DataConI Name Type Name Fixity | VarI Name Type (Maybe Dec) Fixity | TyVarI Name Type Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 18 / 20 Podsumowanie The End. Q&A Literatura Template Haskell - Haskell Wiki QuasiQuotation - Haskell Wiki Template Haskell - GHC User Guide Template metaprogramming for Haskell,Tim Sheard and Simon Peyton Jones, May 2002 Notes on Template Haskell version 2 Typing Template Haskell: Soft Types, Ian Lynagh, August 2004 New directions for Template Haskell - GHC blog Maciej Kotowicz () Template Haskell Wrocław, 14 grudnia 2010 19 / 20