Metaprogramming in Haskell
Table of Contents Template Haskell Generic Programming in Haskell (Type-level Programming)
Table of Contents Template Haskell Generic Programming in Haskell (Type-level Programming)
Template Haskell
Template Haskell Haskell
Template Haskell Haskell C
HOC - Haskell Objective-C binding Class/Instance jmacro JavaScript HAppS lambdabot IRC Bot (IRC )
TH
TH
TH IO
TH IO ( reify )
TH IO ( reify ) DSL
TH
TH ( )
TH ( ) Template Haskell
TH ( ) Template Haskell Q IO
TH ( ) Template Haskell Q IO compile-time wxWidgets, Socket, etc...
TH Features {-# LANGUAGE TemplateHaskell, QuasiQuotes #-} import Language.Haskell.TH splice reify / runIO
DEMO
2 RandomDef.hs
2 RandomDef.hs {-# LANGUAGE TemplateHaskell #-} module Main where import Language.Haskell.TH import System.Random $( do rnd ← runIO $ randomRIO (0,1) let nm = mkName (["a", "b"] !! rnd) m ← [d| main = $(varE $ mkName "a") |] t ← valD (varP nm) (normalB [| putStrLn " `) " |]) [] (´ return (t:m) )
(RandomDef.hs) {-# LANGUAGE TemplateHaskell #-} module Main where import Language.Haskell.TH import System.Random $( do rnd ← runIO $ randomRIO (0,1) let nm = mkName (["a", "b"] !! rnd) m ← [d| main = $(varE $ mkName "a") |] t ← valD (varP nm) (normalB [| putStrLn " `) " |]) [] (´ return (t:m) )
Template Haskell
Template Haskell Exp Dec Pat Type
Template Haskell Exp Dec Pat Type ……(cf. HOC)
Template Haskell Exp Dec Pat Type ……(cf. HOC) Q
putStrLn “Hello!” = AppE (VarE ‘putStrLn) (LitE (stringL “Hello!”)) main :: IO () main = getLine >>= putStrLn [ SigD (mkName "main") (AppT (VarT ''IO) (VarT ''())), FunD (mkName "main") [Clause [] (NormalB $ InfixE (Just $ VarE 'getLine) (VarE '(>>=)) (Just $ VarE 'putStrLn) ) []]]
lib2 = let l=LetS[ValD(VarP $ mkName"it")(NormalB(f"be"))[]] f=VarE . mkName in DoE [ l, l, l, NoBindS $ f"oh",l, NoBindS $ InfixE(Just$ f"speaking")(f"words")(Just $ f "wisdom"),l]
lib2 = let l=LetS[ValD(VarP $ mkName"it")(NormalB(f"be"))[]] f=VarE . mkName in DoE [ l, l, l, NoBindS $ f"oh",l, NoBindS $ InfixE(Just$ f"speaking")(f"words")(Just $ f "wisdom"),l] do let it = be let it = be let it = be oh let it = be speaking `words` wisdom let it = be
k GHCi GHCi> runQ [d| data List a = Cons a (List a) | Nil |] [DataD [] List [PlainTV a_0] [NormalC Cons [(NotStrict,VarT a_0), (NotStrict,AppT (ConT List) (VarT a_0))],NormalC Nil []] []]
[k| |] (“k” ) Q [e| putStrLn “foo” |] (e ) [d| main = putStrLn “:-)” |] [t| Maybe String |] [p| Just 2 |] (GHC HEAD) ( ) `a, ``Maybe ( )
{-# LANGUAGE TemplateHaskell #-} module Main where import Language.Haskell.TH import System.Random $( do rnd ← runIO $ randomRIO (0,1) let nm = mkName (["a", "b"] !! rnd) m ← [d| main = $(varE $ mkName "a") |] t ← valD (varP nm) (normalB [| putStrLn " ( ´ `) " |]) [] return (t:m) )
(RandomDef.hs) {-# LANGUAGE TemplateHaskell #-} module Main where import Language.Haskell.TH import System.Random + $( do rnd ← runIO $ randomRIO (0,1) let nm = mkName (["a", "b"] !! rnd) m ← [d| main = $(varE $ mkName "a") |] t ← valD (varP nm) (normalB [| putStrLn " ( ´ `) " |]) [] return (t:m) )
(Splice)
(Splice) Q
(Splice) Q $( )
(Splice) Q $( )
(Splice) Q $( ) main = $(1 + ‘a) :: $(myType)
(Splice) Q $( ) main = $(1 + ‘a) :: $(myType) $() (6.12 )
(Splice) Q $( ) main = $(1 + ‘a) :: $(myType) $() (6.12 ) Splice (6.12 )
(Splice) Q $( ) main = $(1 + ‘a) :: $(myType) $() (6.12 ) Splice (6.12 ) Splice import
(Splice) Q $( ) main = $(1 + ‘a) :: $(myType) $() (6.12 ) Splice (6.12 ) Splice import
Q Monad
Q Monad
Q Monad IO
Q Monad IO runIO $ ...
Q Monad IO runIO $ ... (reify)
Q Monad IO runIO $ ... (reify) Q
Q Monad IO runIO $ ... (reify) Q GHCi runQ $ reify ''Maybe
IO {-# LANGUAGE TemplateHaskell #-} module Main where import Language.Haskell.THIO Get import System.Random $( do rnd ← runIO $ randomRIO (0,1) let nm = mkName (["a", "b"] !! rnd) m ← [d| main = $(varE $ mkName "a") |] t ← valD (varP nm) (normalB [| putStrLn " `) " |]) [] (´ return (t:m) )
{-# LANGUAGE TemplateHaskell #-} module Main where import Language.Haskell.TH import System.Random $( do rnd ← runIO $ randomRIO (0,1) let nm = mkName (["a", "b"] !! rnd) m ← [d| main = $(varE $ mkName "a") |] t ← valD (varP nm) (normalB [| putStrLn " `) " |]) [] (´ return (t:m) )
reify compile-time ( ) derive DEMO
LISP
LISP EDSL
LISP EDSL
LISP EDSL GHC HEAD
LISP EDSL GHC HEAD [$ident| ... |]
LISP EDSL GHC HEAD [$ident| ... |] ident QuasiQuoter
LISP EDSL GHC HEAD [$ident| ... |] ident QuasiQuoter String → ExpQ String → PatQ
LISP EDSL GHC HEAD [$ident| ... |] ident QuasiQuoter String → ExpQ String → PatQ Graph JSON
mkTweet :: Int → String → JSValue → JSValue mkTweet tid text = [$json| {“status”: { “id”: #int<tid>, “text”: #str<text> }} |] getID :: JSValue → Int getID [$json| “id”:#Int{var} |] = var
mkTweet :: Int → String → JSValue → JSValue mkTweet tid text = [$json| {“status”: { “id”: #int<tid>, “text”: #str<text> }} |] getID :: JSValue → Int getID [$json| “id”:#Int{var} |] = var ( )
mkTweet :: Int → String → JSValue → JSValue mkTweet tid text = [$json| {“status”: { “id”: #int<tid>, “text”: #str<text> }} |] getID :: JSValue → Int getID [$json| “id”:#Int{var} |] = var ( )
JSON data JSON = JSNumber Int | JSString String | ... | Var String deriving (Show, Eq, Ord) -- QuasiQuoter json :: QuasiQuoter json = QuasiQuoter quoteJSONExp quoteJSONPat quoteJSONExp :: String → ExpQ quoteJSONPat :: String → PatQ quoteJSONPat src = ... quoteJSONExp src = ...
JSON data JSON = JSNumber Int | JSString String | ... | Var String deriving (Show, Eq, Ord) -- QuasiQuoter json :: QuasiQuoter json = QuasiQuoter quoteJSONExp quoteJSONPat quoteJSONExp :: String → ExpQ quoteJSONPat :: String → PatQ quoteJSONPat src = ... quoteJSONExp src = ...
JSON data JSON = JSNumber Int | JSString String | ... | Var String deriving (Show, Eq, Ord) -- QuasiQuoter json :: QuasiQuoter json = QuasiQuoter quoteJSONExp quoteJSONPat quoteJSONExp :: String → ExpQ quoteJSONPat :: String → PatQ quoteJSONPat src = ... quoteJSONExp src = ...
JSON data JSON = JSNumber Int | JSString String | ... | Var String deriving (Show, Eq, Ord) -- QuasiQuoter json :: QuasiQuoter json = QuasiQuoter quoteJSONExp quoteJSONPat quoteJSONExp :: String → ExpQ quoteJSONPat :: String → PatQ quoteJSONPat src = ... quoteJSONExp src = ...
dataToExpQ, dataToPatQ
dataToExpQ, dataToPatQ jsonPat src= dataToPatQ (const Nothing `extQ` antiQuoteP) (parseJSON src) antiQuoteP (Var a) = Just (varP (mkName a)) antiQuoteP _ = Nothing
dataToExpQ, dataToPatQ jsonPat src= dataToPatQ (const Nothing `extQ` antiQuoteP) (parseJSON src) antiQuoteP (Var a) = Just (varP (mkName a)) antiQuoteP _ = Nothing
data JSON = JSNumber Int | JSString String | ... | Var String deriving (Show, Eq, Ord, Data, Typeable) ... parseExpr = ... -- Parser quoteJSONPat src = do let exp = parseExpr src dataToPatQ (const Nothing `extQ` antiStrPat) exp antiStrPat :: Expr → Maybe PatQ antiStrPat (Var a) = Just $ varP (mkName a) antiStrPat _ = Nothing
data JSON = JSNumber Int | JSString String | ... | Var String deriving (Show, Eq, Ord, Data, Typeable) ... parseExpr = ... -- Parser quoteJSONPat src = do let exp = parseExpr src dataToPatQ (const Nothing `extQ` antiStrPat) exp antiStrPat :: Expr → Maybe PatQ antiStrPat (Var a) = Just $ varP (mkName a) antiStrPat _ = Nothing
data JSON = JSNumber Int | JSString String | ... | Var String deriving (Show, Eq, Ord, Data, Typeable) ... parseExpr = ... -- Parser quoteJSONPat src = do let exp = parseExpr src dataToPatQ (const Nothing `extQ` antiStrPat) exp antiStrPat :: Expr → Maybe PatQ antiStrPat (Var a) = Just $ varP (mkName a) antiStrPat _ = Nothing Var
…… dataToExpQ extQ …… ……
Generic Programming in Haskell Template Haskell Generic Programming in Haskell (Type-level Programming)
Haskell
Haskell ——Wikipedia
Haskell ——Wikipedia =
Haskell ——Wikipedia =
Haskell ——Wikipedia =
Generic Programming in Haskell (Generics ; GHC ) SYB (Scrap Your Boilerplate) Instant Generics
Generic Programming in Haskell (Generics ; GHC ) SYB (Scrap Your Boilerplate) Instant Generics
Sum of Product
Sum of Product ( )
Sum of Product ( )
Sum of Product ( ) {-# LANGUAGE Generics, TypeOperators #-}
Sum of Product ( ) {-# LANGUAGE Generics, TypeOperators #-} import GHC.Generics
data Bool = False | True = Unit :+: Unit data Maybe a = Nothing | Just a = Unit :+: a Just 12 = Inr 12, Nothing = Inl Unit data List a = Nil | Cons a (List a) = Unit :+: (a :*: (List a)) [1,2,3] = Inr (1 :*: Inr (2 :*: Inr (3 :*: Inl Unit)))
Binary Encode class Bin a where toBin :: a → [Int] fromBin :: [Int] → (a, [Int]) toBin {| Unit |} Unit = [0] toBin {| p :*: q |} (a :*: b) = toBin a ++ toBin b toBin {| p :+: q |} (Inl a) = 0:toBin a toBin {| p :+: q |} (Inr b) = 1:toBin b fromBin {| Unit |} (0:xs) = (Unit, xs) fromBin {| p :*: q |} bin = let (a, bin') = fromBin bin (b, bin'') = fromBin bin' ...
class Bin a where toBin :: a → [Int] fromBin :: [Int] → (a, [Int]) toBin {| Unit |} Unit = [0] toBin {| p :*: q |} (a :*: b) = toBin a ++ toBin b toBin {| p :+: q |} (Inl a) = 0:toBin a toBin {| p :+: q |} (Inr b) = 1:toBin b fromBin {| Unit |} (0:xs) = (Unit, xs) fromBin {| p :*: q |} bin = let (a, bin') = fromBin bin (b, bin'') = fromBin bin' in ...
class Bin a where toBin :: a → [Int] fromBin :: [Int] → (a, [Int]) toBin {| Unit |} Unit = [0] toBin {| p :*: q |} (a :*: b) = toBin a ++ toBin b toBin {| p :+: q |} (Inl a) = 0:toBin a toBin {| p :+: q |} (Inr b) = 1:toBin b fromBin {| Unit |} (0:xs) = (Unit, xs) fromBin {| p :*: q |} bin = let (a, bin') = fromBin bin (b, bin'') = fromBin bin' in (a :*: b, bin’’) ...
( Int, Char) instance instance Bin Int where toBin = .... instance Bin Char where toBin = ... instance Bin a Bin [a] instance (Bin a, Bin b) Bin (a, b) instance Bin a Bin (Maybe a) instance (Bin a, Bin b) Bin (Either a b)
DEMO
default method a [a] Maybe a
Generic Programming in Haskell (Generics ; GHC ) SYB (Scrap Your Boilerplate) Instant Generics
Scrap Your Boilerplate syb Haskell dataToExpQ
Typeable / Data
Typeable / Data Typeable: cast ( )
Typeable / Data Typeable: cast ( ) Data: (gfoldl) cast
Typeable / Data GHC {-# LANGUAGE DeriveDataTypeable #-} data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving (Data, Typeable) Standalone deriving {-# LANGUAGE StandaloneDeriving #-} deriving instance Typeable1 Tree deriving instance Data a Data (Tree a)
-- data Expr = Num Int | Var String | Plus Expr Expr | Minus Expr Expr | Multi Expr Expr | Div Expr Expr deriving (Show, Eq, Data, Typeable) normalize :: Expr → Expr normalize = everywhere (mkT normalize') normalize' (Plus (Num n) (Num m)) = Num (n + m) normalize' (Multi (Num n) (Num m)) = Num (n * m) normalize' (Minus (Num n) (Num m)) = Num (n - m) normalize' (Div (Num n) (Num m)) = Num (n `div` m) normalize' x =x
SYB
SYB
SYB
SYB
SYB mkT :: (b → b) → (a → a)
SYB mkT :: (b → b) → (a → a)
SYB mkT :: (b → b) → (a → a) everywhere :: GenericT → GenericT
SYB mkT :: (b → b) → (a → a) everywhere :: GenericT → GenericT bottom-up
SYB mkT :: (b → b) → (a → a) everywhere :: GenericT → GenericT bottom-up top-down everywhere'
(1) GenericT = ∀a. a → a Transformer mkT fun trans `extT` fun GenericM = ∀a. a → m a : GenericQ = ∀a. a → r Query ( ) `mkQ` fun query `extQ` fun
(2) GenericB = ∀a. a Builder builder `extB` fun GenericR = ∀a. m a Reader mkR fun reader `extR` fun
gmapT :: GenericT → a → a somewhere :: GenericM m → GenecirM m everything :: (r → r → r) → GenericQ r → GenericQ r listify :: (r → Bool) → GenericQ [r] gsize/glength :: GenericQ Int
dataToExpQ dataToExpQ :: Data a GenericQ (Maybe ExpQ) → a → ExpQ (const Nohting `ext` anti)
SYB
SYB
SYB cast
Generic Programming in Haskell (Generics ; GHC ) SYB (Scrap Your Boilerplate) Instant Generics
Instant Generics
Instant Generics (Type families) DPH (Data Parallel Haskell)
Generics
Generics
Generics
Generics
IG Representable a type Rep a data U = U data a :+: b = L a | R b ( ) data a :*: b = a :*: b data C con a = C a data Var p = Var p data Rec p = Rec p
Int, Bool Int, Bool data Maybe a = Nothing | Just a type Rep (Maybe a) = C Maybe_Nothing_ U :+: C Maybe_Just_ (Var a) Just 12 = R(C(Var 12)), Nothing = L(C U)
Int, Bool Int, Bool data Maybe a = Nothing | Just a type Rep (Maybe a) = C Maybe_Nothing_ U :+: C Maybe_Just_ (Var a) Just 12 = R(C(Var 12)), Nothing = L(C U)
1 Binary Encode class Bin a where toBin :: a → [Int] fromBin :: [Int] → (a, [Int]) C, Var, Rec instance Bin U where toBin U = [] fromBin xs = (U, []) instance (Bin a, Bin b) Bin (a :+: b) where toBin (L a) = 0:toBin a toBin (R b) = 1:toBin b fromBin (0:bin) = ... ... instance (Bin a, Bin b) Bin (a :*: b) where toBin (a :*: b) = toBin a ++ toBin b fromBin bin = ... instance Bin Int where ...
def_toBin :: (Representable a, Bin (Rep a)) a → [Int] def_toBin = toBin . from ... instance Bin a Bin [a] where toBin = def_toBin; fromBin = def_fromBin
2 ! class Normalize a where normalize :: a → a instance Normalize U instance Normalize (Var a) ... instance Normalize a Normalize (Rec a) where normalize (Rec a) = Rec (normalize a)
2 ! class Normalize a where normalize :: a → a instance Normalize U instance Normalize (Var a) ... instance Normalize a Normalize (Rec a) where normalize (Rec a) = Rec (normalize a)
2 ! class Normalize a where normalize :: a → a instance Normalize U instance Normalize (Var a) ... instance Normalize a Normalize (Rec a) where normalize (Rec a) = Rec (normalize a)
2 ! class Normalize a where normalize :: a → a instance Normalize U instance Normalize (Var a) ... instance Normalize a Normalize (Rec a) where normalize (Rec a) = Rec (normalize a)
Expr dft_normalize :: (Representable a, Normalize (Rep a)) a→a dft_normalize = to . normalize . from instance Normalize Expr where normalize x = case dft_normalize x of Plus (Num n) (Num m) → Num (n + m) Multi (Num n) (Num m) → Num (n * m) Minus (Num n) (Num m) → Num (n - m) Div (Num n) (Num m) → Num (n `div` m) x →x Var Int, Char
Instant Generics
Instant Generics
Instant Generics
100000(ms) 10000(ms) 1000(ms) 100(ms) 10(ms) 1(ms) geq rmWeights selectInt selectIntAcc SYB Instant Generics
100000(ms) 10000(ms) 1000(ms) 100(ms) 10(ms) 1(ms) geq rmWeights selectInt selectIntAcc SYB Instant Generics
100000(ms) 10000(ms) 1000(ms) 100(ms) 10(ms) 1(ms) geq rmWeights selectInt selectIntAcc SYB Instant Generics
100000(ms) 10000(ms) 1000(ms) 100(ms) 10(ms) 1(ms) geq rmWeights selectInt selectIntAcc SYB Instant Generics
100000(ms) 75000(ms) 50000(ms) 25000(ms) 0(ms) geq rmWeights selectInt selectIntAcc SYB Instant Generics
SYB
Generics SYB IG
GP SYB with class Data Smash ( ) SYB Uniplate MPTC
Questions?
Metaprogramming in Haskell

Metaprogramming in Haskell

  • 1.
    Metaprogramming in Haskell
  • 2.
    Table of Contents TemplateHaskell Generic Programming in Haskell (Type-level Programming)
  • 3.
    Table of Contents TemplateHaskell Generic Programming in Haskell (Type-level Programming)
  • 4.
  • 5.
  • 6.
  • 7.
    HOC - HaskellObjective-C binding Class/Instance jmacro JavaScript HAppS lambdabot IRC Bot (IRC )
  • 8.
  • 9.
  • 10.
    TH IO
  • 11.
    TH IO ( reify )
  • 12.
    TH IO ( reify ) DSL
  • 13.
  • 14.
  • 15.
    TH ( ) Template Haskell
  • 16.
    TH ( ) Template Haskell Q IO
  • 17.
    TH ( ) Template Haskell Q IO compile-time wxWidgets, Socket, etc...
  • 18.
    TH Features {-# LANGUAGE TemplateHaskell, QuasiQuotes #-} import Language.Haskell.TH splice reify / runIO
  • 19.
  • 20.
    2 RandomDef.hs
  • 21.
    2 RandomDef.hs {-# LANGUAGETemplateHaskell #-} module Main where import Language.Haskell.TH import System.Random $( do rnd ← runIO $ randomRIO (0,1) let nm = mkName (["a", "b"] !! rnd) m ← [d| main = $(varE $ mkName "a") |] t ← valD (varP nm) (normalB [| putStrLn " `) " |]) [] (´ return (t:m) )
  • 22.
    (RandomDef.hs) {-# LANGUAGE TemplateHaskell#-} module Main where import Language.Haskell.TH import System.Random $( do rnd ← runIO $ randomRIO (0,1) let nm = mkName (["a", "b"] !! rnd) m ← [d| main = $(varE $ mkName "a") |] t ← valD (varP nm) (normalB [| putStrLn " `) " |]) [] (´ return (t:m) )
  • 24.
  • 25.
    Template Haskell Exp Dec Pat Type
  • 26.
    Template Haskell Exp Dec Pat Type ……(cf. HOC)
  • 27.
    Template Haskell Exp Dec Pat Type ……(cf. HOC) Q
  • 28.
    putStrLn “Hello!” = AppE (VarE ‘putStrLn) (LitE (stringL “Hello!”)) main :: IO () main = getLine >>= putStrLn [ SigD (mkName "main") (AppT (VarT ''IO) (VarT ''())), FunD (mkName "main") [Clause [] (NormalB $ InfixE (Just $ VarE 'getLine) (VarE '(>>=)) (Just $ VarE 'putStrLn) ) []]]
  • 29.
    lib2 = let l=LetS[ValD(VarP $ mkName"it")(NormalB(f"be"))[]] f=VarE . mkName in DoE [ l, l, l, NoBindS $ f"oh",l, NoBindS $ InfixE(Just$ f"speaking")(f"words")(Just $ f "wisdom"),l]
  • 30.
    lib2 = let l=LetS[ValD(VarP $ mkName"it")(NormalB(f"be"))[]] f=VarE . mkName in DoE [ l, l, l, NoBindS $ f"oh",l, NoBindS $ InfixE(Just$ f"speaking")(f"words")(Just $ f "wisdom"),l] do let it = be let it = be let it = be oh let it = be speaking `words` wisdom let it = be
  • 31.
    k GHCi GHCi> runQ [d| data List a = Cons a (List a) | Nil |] [DataD [] List [PlainTV a_0] [NormalC Cons [(NotStrict,VarT a_0), (NotStrict,AppT (ConT List) (VarT a_0))],NormalC Nil []] []]
  • 32.
    [k| |] (“k” ) Q [e| putStrLn “foo” |] (e ) [d| main = putStrLn “:-)” |] [t| Maybe String |] [p| Just 2 |] (GHC HEAD) ( ) `a, ``Maybe ( )
  • 33.
    {-# LANGUAGE TemplateHaskell#-} module Main where import Language.Haskell.TH import System.Random $( do rnd ← runIO $ randomRIO (0,1) let nm = mkName (["a", "b"] !! rnd) m ← [d| main = $(varE $ mkName "a") |] t ← valD (varP nm) (normalB [| putStrLn " ( ´ `) " |]) [] return (t:m) )
  • 34.
    (RandomDef.hs) {-# LANGUAGE TemplateHaskell#-} module Main where import Language.Haskell.TH import System.Random + $( do rnd ← runIO $ randomRIO (0,1) let nm = mkName (["a", "b"] !! rnd) m ← [d| main = $(varE $ mkName "a") |] t ← valD (varP nm) (normalB [| putStrLn " ( ´ `) " |]) [] return (t:m) )
  • 35.
  • 36.
  • 37.
    (Splice) Q $( )
  • 38.
    (Splice) Q $( )
  • 39.
    (Splice) Q $( ) main = $(1 + ‘a) :: $(myType)
  • 40.
    (Splice) Q $( ) main = $(1 + ‘a) :: $(myType) $() (6.12 )
  • 41.
    (Splice) Q $( ) main = $(1 + ‘a) :: $(myType) $() (6.12 ) Splice (6.12 )
  • 42.
    (Splice) Q $( ) main = $(1 + ‘a) :: $(myType) $() (6.12 ) Splice (6.12 ) Splice import
  • 43.
    (Splice) Q $( ) main = $(1 + ‘a) :: $(myType) $() (6.12 ) Splice (6.12 ) Splice import
  • 44.
  • 45.
  • 46.
  • 47.
    Q Monad IO runIO $ ...
  • 48.
    Q Monad IO runIO $ ... (reify)
  • 49.
    Q Monad IO runIO $ ... (reify) Q
  • 50.
    Q Monad IO runIO $ ... (reify) Q GHCi runQ $ reify ''Maybe
  • 51.
    IO {-# LANGUAGE TemplateHaskell#-} module Main where import Language.Haskell.THIO Get import System.Random $( do rnd ← runIO $ randomRIO (0,1) let nm = mkName (["a", "b"] !! rnd) m ← [d| main = $(varE $ mkName "a") |] t ← valD (varP nm) (normalB [| putStrLn " `) " |]) [] (´ return (t:m) )
  • 52.
    {-# LANGUAGE TemplateHaskell#-} module Main where import Language.Haskell.TH import System.Random $( do rnd ← runIO $ randomRIO (0,1) let nm = mkName (["a", "b"] !! rnd) m ← [d| main = $(varE $ mkName "a") |] t ← valD (varP nm) (normalB [| putStrLn " `) " |]) [] (´ return (t:m) )
  • 53.
    reify compile-time ( ) derive DEMO
  • 55.
  • 56.
    LISP EDSL
  • 57.
    LISP EDSL
  • 58.
    LISP EDSL GHC HEAD
  • 59.
    LISP EDSL GHC HEAD [$ident| ... |]
  • 60.
    LISP EDSL GHC HEAD [$ident| ... |] ident QuasiQuoter
  • 61.
    LISP EDSL GHC HEAD [$ident| ... |] ident QuasiQuoter String → ExpQ String → PatQ
  • 62.
    LISP EDSL GHC HEAD [$ident| ... |] ident QuasiQuoter String → ExpQ String → PatQ Graph JSON
  • 63.
    mkTweet :: Int→ String → JSValue → JSValue mkTweet tid text = [$json| {“status”: { “id”: #int<tid>, “text”: #str<text> }} |] getID :: JSValue → Int getID [$json| “id”:#Int{var} |] = var
  • 64.
    mkTweet :: Int→ String → JSValue → JSValue mkTweet tid text = [$json| {“status”: { “id”: #int<tid>, “text”: #str<text> }} |] getID :: JSValue → Int getID [$json| “id”:#Int{var} |] = var ( )
  • 65.
    mkTweet :: Int→ String → JSValue → JSValue mkTweet tid text = [$json| {“status”: { “id”: #int<tid>, “text”: #str<text> }} |] getID :: JSValue → Int getID [$json| “id”:#Int{var} |] = var ( )
  • 66.
    JSON data JSON =JSNumber Int | JSString String | ... | Var String deriving (Show, Eq, Ord) -- QuasiQuoter json :: QuasiQuoter json = QuasiQuoter quoteJSONExp quoteJSONPat quoteJSONExp :: String → ExpQ quoteJSONPat :: String → PatQ quoteJSONPat src = ... quoteJSONExp src = ...
  • 67.
    JSON data JSON =JSNumber Int | JSString String | ... | Var String deriving (Show, Eq, Ord) -- QuasiQuoter json :: QuasiQuoter json = QuasiQuoter quoteJSONExp quoteJSONPat quoteJSONExp :: String → ExpQ quoteJSONPat :: String → PatQ quoteJSONPat src = ... quoteJSONExp src = ...
  • 68.
    JSON data JSON =JSNumber Int | JSString String | ... | Var String deriving (Show, Eq, Ord) -- QuasiQuoter json :: QuasiQuoter json = QuasiQuoter quoteJSONExp quoteJSONPat quoteJSONExp :: String → ExpQ quoteJSONPat :: String → PatQ quoteJSONPat src = ... quoteJSONExp src = ...
  • 69.
    JSON data JSON =JSNumber Int | JSString String | ... | Var String deriving (Show, Eq, Ord) -- QuasiQuoter json :: QuasiQuoter json = QuasiQuoter quoteJSONExp quoteJSONPat quoteJSONExp :: String → ExpQ quoteJSONPat :: String → PatQ quoteJSONPat src = ... quoteJSONExp src = ...
  • 72.
  • 73.
    dataToExpQ, dataToPatQ jsonPat src=dataToPatQ (const Nothing `extQ` antiQuoteP) (parseJSON src) antiQuoteP (Var a) = Just (varP (mkName a)) antiQuoteP _ = Nothing
  • 74.
    dataToExpQ, dataToPatQ jsonPat src=dataToPatQ (const Nothing `extQ` antiQuoteP) (parseJSON src) antiQuoteP (Var a) = Just (varP (mkName a)) antiQuoteP _ = Nothing
  • 75.
    data JSON =JSNumber Int | JSString String | ... | Var String deriving (Show, Eq, Ord, Data, Typeable) ... parseExpr = ... -- Parser quoteJSONPat src = do let exp = parseExpr src dataToPatQ (const Nothing `extQ` antiStrPat) exp antiStrPat :: Expr → Maybe PatQ antiStrPat (Var a) = Just $ varP (mkName a) antiStrPat _ = Nothing
  • 76.
    data JSON =JSNumber Int | JSString String | ... | Var String deriving (Show, Eq, Ord, Data, Typeable) ... parseExpr = ... -- Parser quoteJSONPat src = do let exp = parseExpr src dataToPatQ (const Nothing `extQ` antiStrPat) exp antiStrPat :: Expr → Maybe PatQ antiStrPat (Var a) = Just $ varP (mkName a) antiStrPat _ = Nothing
  • 77.
    data JSON =JSNumber Int | JSString String | ... | Var String deriving (Show, Eq, Ord, Data, Typeable) ... parseExpr = ... -- Parser quoteJSONPat src = do let exp = parseExpr src dataToPatQ (const Nothing `extQ` antiStrPat) exp antiStrPat :: Expr → Maybe PatQ antiStrPat (Var a) = Just $ varP (mkName a) antiStrPat _ = Nothing Var
  • 78.
    …… dataToExpQ extQ …… ……
  • 79.
    Generic Programming inHaskell Template Haskell Generic Programming in Haskell (Type-level Programming)
  • 80.
  • 81.
    Haskell ——Wikipedia
  • 82.
    Haskell ——Wikipedia =
  • 83.
    Haskell ——Wikipedia =
  • 84.
    Haskell ——Wikipedia =
  • 86.
    Generic Programming in Haskell (Generics ; GHC ) SYB (Scrap Your Boilerplate) Instant Generics
  • 87.
    Generic Programming in Haskell (Generics ; GHC ) SYB (Scrap Your Boilerplate) Instant Generics
  • 90.
  • 91.
  • 92.
  • 93.
    Sum of Product ( ) {-# LANGUAGE Generics, TypeOperators #-}
  • 94.
    Sum of Product ( ) {-# LANGUAGE Generics, TypeOperators #-} import GHC.Generics
  • 95.
    data Bool =False | True = Unit :+: Unit data Maybe a = Nothing | Just a = Unit :+: a Just 12 = Inr 12, Nothing = Inl Unit data List a = Nil | Cons a (List a) = Unit :+: (a :*: (List a)) [1,2,3] = Inr (1 :*: Inr (2 :*: Inr (3 :*: Inl Unit)))
  • 96.
    Binary Encode class Bina where toBin :: a → [Int] fromBin :: [Int] → (a, [Int]) toBin {| Unit |} Unit = [0] toBin {| p :*: q |} (a :*: b) = toBin a ++ toBin b toBin {| p :+: q |} (Inl a) = 0:toBin a toBin {| p :+: q |} (Inr b) = 1:toBin b fromBin {| Unit |} (0:xs) = (Unit, xs) fromBin {| p :*: q |} bin = let (a, bin') = fromBin bin (b, bin'') = fromBin bin' ...
  • 97.
    class Bin awhere toBin :: a → [Int] fromBin :: [Int] → (a, [Int]) toBin {| Unit |} Unit = [0] toBin {| p :*: q |} (a :*: b) = toBin a ++ toBin b toBin {| p :+: q |} (Inl a) = 0:toBin a toBin {| p :+: q |} (Inr b) = 1:toBin b fromBin {| Unit |} (0:xs) = (Unit, xs) fromBin {| p :*: q |} bin = let (a, bin') = fromBin bin (b, bin'') = fromBin bin' in ...
  • 98.
    class Bin awhere toBin :: a → [Int] fromBin :: [Int] → (a, [Int]) toBin {| Unit |} Unit = [0] toBin {| p :*: q |} (a :*: b) = toBin a ++ toBin b toBin {| p :+: q |} (Inl a) = 0:toBin a toBin {| p :+: q |} (Inr b) = 1:toBin b fromBin {| Unit |} (0:xs) = (Unit, xs) fromBin {| p :*: q |} bin = let (a, bin') = fromBin bin (b, bin'') = fromBin bin' in (a :*: b, bin’’) ...
  • 99.
    ( Int, Char) instance instance Bin Int where toBin = .... instance Bin Char where toBin = ... instance Bin a Bin [a] instance (Bin a, Bin b) Bin (a, b) instance Bin a Bin (Maybe a) instance (Bin a, Bin b) Bin (Either a b)
  • 100.
  • 101.
    default method a [a] Maybe a
  • 102.
    Generic Programming in Haskell (Generics ; GHC ) SYB (Scrap Your Boilerplate) Instant Generics
  • 103.
    Scrap Your Boilerplate syb Haskell dataToExpQ
  • 104.
  • 105.
    Typeable / Data Typeable: cast ( )
  • 106.
    Typeable / Data Typeable: cast ( ) Data: (gfoldl) cast
  • 107.
    Typeable / Data GHC {-# LANGUAGE DeriveDataTypeable #-} data Tree a = Leaf a | Branch (Tree a) (Tree a) deriving (Data, Typeable) Standalone deriving {-# LANGUAGE StandaloneDeriving #-} deriving instance Typeable1 Tree deriving instance Data a Data (Tree a)
  • 108.
    -- data Expr =Num Int | Var String | Plus Expr Expr | Minus Expr Expr | Multi Expr Expr | Div Expr Expr deriving (Show, Eq, Data, Typeable) normalize :: Expr → Expr normalize = everywhere (mkT normalize') normalize' (Plus (Num n) (Num m)) = Num (n + m) normalize' (Multi (Num n) (Num m)) = Num (n * m) normalize' (Minus (Num n) (Num m)) = Num (n - m) normalize' (Div (Num n) (Num m)) = Num (n `div` m) normalize' x =x
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
    SYB mkT :: (b→ b) → (a → a)
  • 114.
    SYB mkT :: (b→ b) → (a → a)
  • 115.
    SYB mkT :: (b→ b) → (a → a) everywhere :: GenericT → GenericT
  • 116.
    SYB mkT :: (b→ b) → (a → a) everywhere :: GenericT → GenericT bottom-up
  • 117.
    SYB mkT :: (b→ b) → (a → a) everywhere :: GenericT → GenericT bottom-up top-down everywhere'
  • 118.
    (1) GenericT = ∀a.a → a Transformer mkT fun trans `extT` fun GenericM = ∀a. a → m a : GenericQ = ∀a. a → r Query ( ) `mkQ` fun query `extQ` fun
  • 119.
    (2) GenericB = ∀a.a Builder builder `extB` fun GenericR = ∀a. m a Reader mkR fun reader `extR` fun
  • 120.
    gmapT :: GenericT→ a → a somewhere :: GenericM m → GenecirM m everything :: (r → r → r) → GenericQ r → GenericQ r listify :: (r → Bool) → GenericQ [r] gsize/glength :: GenericQ Int
  • 121.
    dataToExpQ dataToExpQ :: Data a GenericQ (Maybe ExpQ) → a → ExpQ (const Nohting `ext` anti)
  • 122.
  • 123.
  • 124.
  • 125.
    Generic Programming in Haskell (Generics ; GHC ) SYB (Scrap Your Boilerplate) Instant Generics
  • 126.
  • 127.
    Instant Generics (Type families) DPH (Data Parallel Haskell)
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
    IG Representable a type Rep a data U = U data a :+: b = L a | R b ( ) data a :*: b = a :*: b data C con a = C a data Var p = Var p data Rec p = Rec p
  • 135.
    Int, Bool Int, Bool data Maybe a = Nothing | Just a type Rep (Maybe a) = C Maybe_Nothing_ U :+: C Maybe_Just_ (Var a) Just 12 = R(C(Var 12)), Nothing = L(C U)
  • 136.
    Int, Bool Int, Bool data Maybe a = Nothing | Just a type Rep (Maybe a) = C Maybe_Nothing_ U :+: C Maybe_Just_ (Var a) Just 12 = R(C(Var 12)), Nothing = L(C U)
  • 137.
    1 Binary Encode class Bin a where toBin :: a → [Int] fromBin :: [Int] → (a, [Int]) C, Var, Rec instance Bin U where toBin U = [] fromBin xs = (U, []) instance (Bin a, Bin b) Bin (a :+: b) where toBin (L a) = 0:toBin a toBin (R b) = 1:toBin b fromBin (0:bin) = ... ... instance (Bin a, Bin b) Bin (a :*: b) where toBin (a :*: b) = toBin a ++ toBin b fromBin bin = ... instance Bin Int where ...
  • 138.
    def_toBin :: (Representablea, Bin (Rep a)) a → [Int] def_toBin = toBin . from ... instance Bin a Bin [a] where toBin = def_toBin; fromBin = def_fromBin
  • 139.
    2 ! class Normalize a where normalize :: a → a instance Normalize U instance Normalize (Var a) ... instance Normalize a Normalize (Rec a) where normalize (Rec a) = Rec (normalize a)
  • 140.
    2 ! class Normalize a where normalize :: a → a instance Normalize U instance Normalize (Var a) ... instance Normalize a Normalize (Rec a) where normalize (Rec a) = Rec (normalize a)
  • 141.
    2 ! class Normalize a where normalize :: a → a instance Normalize U instance Normalize (Var a) ... instance Normalize a Normalize (Rec a) where normalize (Rec a) = Rec (normalize a)
  • 142.
    2 ! class Normalize a where normalize :: a → a instance Normalize U instance Normalize (Var a) ... instance Normalize a Normalize (Rec a) where normalize (Rec a) = Rec (normalize a)
  • 143.
    Expr dft_normalize :: (Representablea, Normalize (Rep a)) a→a dft_normalize = to . normalize . from instance Normalize Expr where normalize x = case dft_normalize x of Plus (Num n) (Num m) → Num (n + m) Multi (Num n) (Num m) → Num (n * m) Minus (Num n) (Num m) → Num (n - m) Div (Num n) (Num m) → Num (n `div` m) x →x Var Int, Char
  • 144.
  • 145.
  • 146.
  • 147.
    100000(ms) 10000(ms) 1000(ms) 100(ms) 10(ms) 1(ms) geq rmWeights selectInt selectIntAcc SYB Instant Generics
  • 148.
    100000(ms) 10000(ms) 1000(ms) 100(ms) 10(ms) 1(ms) geq rmWeights selectInt selectIntAcc SYB Instant Generics
  • 149.
    100000(ms) 10000(ms) 1000(ms) 100(ms) 10(ms) 1(ms) geq rmWeights selectInt selectIntAcc SYB Instant Generics
  • 150.
    100000(ms) 10000(ms) 1000(ms) 100(ms) 10(ms) 1(ms) geq rmWeights selectInt selectIntAcc SYB Instant Generics
  • 151.
    100000(ms) 75000(ms) 50000(ms) 25000(ms) 0(ms) geq rmWeights selectInt selectIntAcc SYB Instant Generics
  • 152.
  • 153.
  • 154.
    GP SYB with class Data Smash ( ) SYB Uniplate MPTC
  • 155.