Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Invertible-syntax 入門

4,327 views

Published on

HIMA' #6 発表資料。

Parser と Pretty Printer を統合するこころみであるところの invertible-syntax の説明と、その基盤である partial-isomorphisms の解説です。

Template Haskell もあるよ!

  • Be the first to comment

Invertible-syntax 入門

  1. 1. invertible-syntax (TH ) Hiromi Ishii a.k.a. @mr_konn
  2. 2. About myself...• id:mr_konn / @mr_konn• Template Haskell• P Haskell
  3. 3. TOC• invertible-syntax• JSON Parser Pretty Printer• Inside invertible-syntax• Real World Template Haskell
  4. 4. TOC• invertible-syntax• JSON Parser Pretty Printer• Inside invertible-syntax• Real World Template Haskell
  5. 5. invertible-syntax
  6. 6. Haskeller
  7. 7. Haskeller•
  8. 8. Haskeller• • Web JSON YAML……
  9. 9. Haskeller• • Web JSON YAML…… •
  10. 10. Haskeller• • Web JSON YAML…… • • Java C
  11. 11. Haskeller• • Web JSON YAML…… • • Java C•
  12. 12. • Parser Pretty Printer
  13. 13. • Parser Pretty Printer • Parser
  14. 14. • Parser Pretty Printer • Parser • (Parsec, Happy...)
  15. 15. • Parser Pretty Printer • Parser • (Parsec, Happy...) •
  16. 16. • Parser Pretty Printer • Parser • (Parsec, Happy...) • • Pretty Printer
  17. 17. • Parser Pretty Printer • Parser • (Parsec, Happy...) • • Pretty Printer • …… (Show, HughesPJ...)
  18. 18. • Parser Pretty Printer • Parser • (Parsec, Happy...) • • Pretty Printer • …… (Show, HughesPJ...) • ……
  19. 19. • Parser Pretty Printer • • Don’t Repeat Yourself! • Pretty Printer ••
  20. 20. invertible-syntax
  21. 21. invertible-syntax• Parser Pretty Printer • Syntax Description • Applicative• • Parser Pretty Printer
  22. 22. JSON
  23. 23. JSON• JSON • •data Slot = Slot { key :: String, val :: JSON }data JSON = Number !Integer | Null | Bool !Bool | Array ![JSON] | String String | Object ![Slot]
  24. 24. JSONPretty.hsimport Text.PrettyPrint.HughesPJpretty :: Printer JSON -- Printer a = a → Docpretty (Object jss) = braces $ hcat $ intersperse comma $ map slot jsspretty (Array jss) = brackets $ hcat $ intersperse comma $ map pretty jsspretty (String str) = doubleQuotes $ text strpretty (Null) = text "null"pretty (Bool b) = case b of True → text "true" False → text "false"pretty (Number int) = integer intslot s = doubleQuotes (text $ key s) <> colon <+> sub (val s)
  25. 25. JSONParsec.hsimport Text.Parsecjson, jsobj, ..., jsnumber :: Parser JSONjson = jsobj <|> jsarray <|> ... <|> jsbool <|> jsnumberjsobj = Object <$> between (symbol "{") (symbol "}") (term `sepBy` symbol ",") where term = Slot <$> str <* symbol ":" <*> jsonjsarray = Array <$> between (symbol "[") (symbol "]") (json `sepBy` symbol ",")jsstring = String <$> strjsnull = Null <$ symbol "null"jsbool = Bool True <$ symbol "true" <|> Bool False <$ symbol "false"jsnumber = Number . read <$> many1 digitstr = between (spaces *> char ") (char " <* spaces) (many $ noneOf """)
  26. 26. JSONInvertible.hsdefineIsomorphisms JSONjson, jsobj, ..., jsnumber :: Syntax f f JSONjson = jsobj <|> jsarray <|> ... <|> jsbool <|> jsnumberjsobj = object <$> between (symbol "{") (symbol "}") (term `sepBy` symbol ",") where term = slot <$> str <* skipSpace <* text ":" <*> jsonjsarray = array <$> between (symbol "[") (symbol "]") (json `sepBy` symbol ",")jsstring = string <$> strjsnull = null <$> symbol "null"jsbool = bool . element True <$> symbol "true" <|> bool . element False <$> symbol "false"jsnumber = number . numIso <$> many1 digitstr = between (optSpace *> text """) (text """ <* optSpace) (many (subset (/=") <$> token))numIso = Iso read’ show’ where read = liftM fst . listToMaybe . reads show = return . show
  27. 27. • Syntax f f JSON • Syntax Description • pure token• <$> <$ <*>
  28. 28. • defineIsomorphisms ……•• (<$) (<$>)• Iso
  29. 29. Insideinvertible-sytnax
  30. 30. Parser Priner
  31. 31. Parser Priner• Iso :
  32. 32. Parser Priner• Iso : • data Iso a b = Iso (a→Maybe b) (b→Maybe a)
  33. 33. Parser Priner• Iso : • data Iso a b = Iso (a→Maybe b) (b→Maybe a) •
  34. 34. Parser Priner• Iso : • data Iso a b = Iso (a→Maybe b) (b→Maybe a) • • Iso Category
  35. 35. Parser Priner• Iso : • data Iso a b = Iso (a→Maybe b) (b→Maybe a) • • Iso Category • id (.)
  36. 36. Parser Priner• Iso : • data Iso a b = Iso (a→Maybe b) (b→Maybe a) • • Iso Category • id (.)• IsoFunctor
  37. 37. Iso 1 numIso = Iso read’ show’ where read = liftM fst . listToMaybe . reads show = return . show•• Control.Isomorphism.Partial.Unsafe• • Iso
  38. 38. Iso 2• import Control.Isomorphism.Partial• element :: α → Iso α () • ()• subset :: (α → Bool) → Iso α α •• foldl :: Iso (α,β) α → Iso (α,[β]) α• (***), associate, iterate, unit ……
  39. 39. IsoFunctor• Functor = • fmap :: (α→β) → f α → f β • α→β Iso α β … class IsoFunctor δ where (<$>) :: Iso α β → δ α → δ β•
  40. 40. partial-isomorphisms
  41. 41. invertible-syntaxApplicative
  42. 42. invertible-syntaxApplicative
  43. 43. invertible-syntaxApplicative
  44. 44. • (<*>)• (<*>) :: δ (α → β) → δ α → δ β• Iso α β …… class IsoApplicative δ where (<*>) :: δ (Iso α β) → δ α → δ β• Parser • Iso α β α
  45. 45. Printerinstance IsoApplicative Printer where (<*>) pab pa b = ……
  46. 46. Printer instance IsoApplicative Printer where (<*>) pab pa b = ……• (<*>) :: Printer (Iso α β) → Printer α → Printer β = ((Iso α β)→Doc) → (α→Doc) → β → Doc
  47. 47. Printer instance IsoApplicative Printer where (<*>) pab pa b = ……• (<*>) :: Printer (Iso α β) → Printer α → Printer β = ((Iso α β)→Doc) → (α→Doc) → β → Doc•β
  48. 48. Printer instance IsoApplicative Printer where (<*>) pab pa b = ……• (<*>) :: Printer (Iso α β) → Printer α → Printer β = ((Iso α β)→Doc) → (α→Doc) → β → Doc•β • ……
  49. 49. Printer instance IsoApplicative Printer where (<*>) pab pa b = ……• (<*>) :: Printer (Iso α β) → Printer α → Printer β = ((Iso α β)→Doc) → (α→Doc) → β → Doc•β • ……• ……
  50. 50. • Applicative
  51. 51. • Applicative • Slot <$> key <*> val
  52. 52. • Applicative • Slot <$> key <*> val • Slot :: String → JSON → (String, JSON)
  53. 53. • Applicative • Slot <$> key <*> val • Slot :: String → JSON → (String, JSON) • slot :: Iso String (Iso JSON Slot)
  54. 54. • Applicative • Slot <$> key <*> val • Slot :: String → JSON → (String, JSON) • slot :: Iso String (Iso JSON Slot) • slot <$> key :: δ (Iso JSON Slot)
  55. 55. ……
  56. 56. ……• slot :: Iso (String, JSON) Slot
  57. 57. ……• slot :: Iso (String, JSON) Slot • slot <$> key <*> val :: δ Slot ……
  58. 58. ……• slot :: Iso (String, JSON) Slot • slot <$> key <*> val :: δ Slot …… • slot <$> (key <*> val) ……
  59. 59. ……• slot :: Iso (String, JSON) Slot • slot <$> key <*> val :: δ Slot …… • slot <$> (key <*> val) …… • (<*>) :: δ α → δ β → δ (α, β)
  60. 60. ProductFunctor class ProductFunctor δ where (<*>) :: δ α → δ β → δ (α, β) infix 5 <$> infixr 6 <*>• Parser Printer•
  61. 61. Isonull :: Iso () JSONnull = Iso to from where to _ = Just Null from Null = Just () from _ = Nothingnumber :: Iso Integer JSONnumber = Iso to from where to = Just . Number from (Number int) = Just int from _ = Nothingslot :: Iso (String, JSON) Slotslot = Iso to from where to (a,b) = Just $ Slot a b from (Slot a b) = Just (a,b)
  62. 62. class Alternative δ where (<|>) :: δ α → δ α → δ α empty :: δ α • Applicative instance• token• pure • Syntax
  63. 63. class IsoFunctor δ where (<$>) :: Iso α β → δ α → δ βclass ProductFunctor δ where (<*>) :: δ α → δ β → δ (α, β)class Alternative δ where (<|>) :: δ α → δ α → δ α empty :: δ αclass ( IsoFunctor δ, ProductFunctor δ , Alternative δ ) Syntax δ where pure :: α → δ α token :: δ Char
  64. 64.
  65. 65. •• many, sepBy, chainl1, text, between
  66. 66. •• many, sepBy, chainl1, text, between • +
  67. 67. •• many, sepBy, chainl1, text, between • +• skipSpace, sepSpace, optSpace
  68. 68. •• many, sepBy, chainl1, text, between • +• skipSpace, sepSpace, optSpace •
  69. 69. •• many, sepBy, chainl1, text, between • +• skipSpace, sepSpace, optSpace • • Printer
  70. 70. •• many, sepBy, chainl1, text, between • +• skipSpace, sepSpace, optSpace • • Printer • sep opt
  71. 71. • skipSpace sepSpace optSpace • • “ntr”
  72. 72. read/show invertible-syntax Parsec/HughesPJ ( )
  73. 73. •• invertible-syntax Parser Printer Naive • • Proof of Concept
  74. 74. • Parsec HughesPJ Syntax
  75. 75. • Parsec HughesPJ Syntax •
  76. 76. • Parsec HughesPJ Syntax • • (<|>)
  77. 77. • Parsec HughesPJ Syntax • • (<|>) •
  78. 78. • Parsec HughesPJ Syntax • • (<|>) ••
  79. 79. • Parsec HughesPJ Syntax • • (<|>) •••
  80. 80. ADT Iso
  81. 81. defineIsomorphisms
  82. 82. Real WorldTemplate Haskell defineIsomorphisms TH
  83. 83. null :: Iso () JSONnull = Iso to from where to _ = Just Null from Null = Just () from _ = Nothingnumber :: Iso Integer JSONnumber = Iso to from where to a = Just $ Number a from (Number int) = Just int from _ = Nothingslot :: Iso (String, JSON) Slotslot = Iso to from where to (a,b) = Just $ Slot a b from (Slot a b) = Just (a,b)
  84. 84. • data Hoge• • Iso () Hoge • Iso (a, (b, ...)) Hoge
  85. 85. • from • Just $ a b c ...• to • Nothing•
  86. 86. • • reify• • …… Exp • …… Type
  87. 87. TH• Metaprogramming in Haskell
  88. 88. • • • E ,P ,T ,D , C , B Body, L • type HogeQ = Q Hoge • (LamE lamE ) • Q • lamE :: [PatQ] → ExpQ→ ExpQ
  89. 89. • defineIsomorphisms :: Name → Q [Dec] • data newtype defineIsomorphisms :: Name → Q [Dec] defineIsomorphisms d = do TyConI dec ← reify d cs ← decConstructors dec mapM (defFromCon (wildcard cs)) cs decConstructors :: Dec -> Q [Con] decConstructors (DataD _ _ _ cs _) = return cs decConstructors (NewtypeD _ _ _ c _)= return [c] decConstructors _ = error “not supported!”
  90. 90. • wildcard • case { _ → Nothing }• defFromCon • rename ( )wildcard :: [Con] -> [MatchQ]wildcard cs = if length cs > 1 then [match (wildP) (normalB [| Nothing |]) []] else []defFromCon :: [MatchQ] -> Con -> DecQdefFromCon wc con = funD (rename (conName con)) [clause [] (normalB (isoFromCon wc con)) []]
  91. 91. •isoFromCon :: [MatchQ] -> Con -> ExpQ IsoisoFromCon wildcard con = do let c = conName con let fs = conFields con -- let n = length fs -- (ps, vs) ← genPE n -- v ← newName "x" let f = lamE [nested tupP ps] -- [| Just $(foldl appE (conE c) vs) |] let g = lamE [varP v] (caseE (varE v) $ [ match (conP c ps) -- Con (a,(b,..) → (normalB [| Just $(nested tupE vs) |]) [] ] ++ wildcard) -- case [| Iso $f $g |] -- from/to λ Iso
  92. 92. Any Questions?

×