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

Podobne dokumenty