round tripping balls
play

Round-Tripping Balls Building A Bi-Directional Printer/Parser 1 / - PowerPoint PPT Presentation

Round-Tripping Balls Building A Bi-Directional Printer/Parser 1 / 46 Introducing: Enterprise JSON 2 / 46 Introducing: Enterprise JSON datetime "27/6/2013 10:29 pm" 2 / 46 Introducing: Enterprise JSON datetime


  1. Round-Tripping Balls Building A Bi-Directional Printer/Parser 1 / 46

  2. Introducing: Enterprise JSON 2 / 46

  3. Introducing: Enterprise JSON “datetime” "27/6/2013 10:29 pm" 2 / 46

  4. Introducing: Enterprise JSON “datetime” "27/6/2013 10:29 pm" “date” "12/12/2012" 2 / 46

  5. Introducing: Enterprise JSON “datetime” "27/6/2013 10:29 pm" “date” "12/12/2012" “mmdddate” "12/12" 2 / 46

  6. Introducing: Enterprise JSON “datetime” "27/6/2013 10:29 pm" “date” "12/12/2012" “mmdddate” "12/12" “mmyydate” "12/2012" 2 / 46

  7. Introducing: Enterprise JSON “datetime” "27/6/2013 10:29 pm" “date” "12/12/2012" “mmdddate” "12/12" “mmyydate” "12/2012" "12.2012" 2 / 46

  8. Introducing: Enterprise JSON “datetime” "27/6/2013 10:29 pm" “date” "12/12/2012" “mmdddate” "12/12" “mmyydate” "12/2012" "12.2012" "122012" 2 / 46

  9. Introducing: Enterprise JSON “checkbox” "T" 3 / 46

  10. Introducing: Enterprise JSON “checkbox” "T" “currency”, “currency2” and “poscurrency” "00.03" 3 / 46

  11. Introducing: Enterprise JSON “checkbox” "T" “currency”, “currency2” and “poscurrency” "00.03" “posfloat”, “nonnegfloat” "2.718281828459045" 3 / 46

  12. Introducing: Enterprise JSON Figure 1: Concern for sanity 4 / 46

  13. A wild paper appears! 5 / 46

  14. Given a datatype: data List a = Nil | Cons a (List a) 6 / 46

  15. We define a Printer 1 “combinator” type Printer a = a -> Doc printMany :: Printer a -> Printer (List a) printMany p list = case list of Nil -> text "" Cons x xs -> p x <> printMany p xs 7 / 46

  16. And a Parser 2 “combinator” newtype Parser a = Parser (String -> [(a, String)]) parseMany :: Parser a -> Parser (List a) parseMany p = const Nil <$> text "" <|> Cons <$> p <*> parseMany p 8 / 46

  17. It would be nice if. . . combined :: Unicorn x => x a -> x (List a) combined p = magic Nil <$> fairies "" <|> Cons <$> p <*> parseMany p 9 / 46

  18. co/contravariance newtype Parser a = Parser (String -> [(a, String)]) (<$>) :: (a -> b) -> Parser a -> Parser b f <$> Parser p = Parser $ (fmap . first) f . p 10 / 46

  19. co/contravariance newtype Parser a = Parser (String -> [(a, String)]) (<$>) :: (a -> b) -> Parser a -> Parser b f <$> Parser p = Parser $ (fmap . first) f . p type Printer a = a -> Doc (<$>) :: (a -> b) -> Printer a -> Printer b 10 / 46

  20. co/contravariance newtype Parser a = Parser (String -> [(a, String)]) (<$>) :: (a -> b) -> Parser a -> Parser b f <$> Parser p = Parser $ (fmap . first) f . p type Printer a = a -> Doc (<$>) :: (a -> b) -> Printer a -> Printer b Can you implement this? 10 / 46

  21. co/contravariance Covariant newtype Parser a = Parser (String -> [(a, String)]) (<$>) :: (a -> b) -> Parser a -> Parser b type Printer a = a -> Doc (<$>) :: (b -> a) -> Printer a -> Printer b Contravariant 11 / 46

  22. The solution: Partial Isomorphisms 3 data Iso a b = Iso { apply :: a -> Maybe b , unapply :: b -> Maybe a } 12 / 46

  23. The solution: IsoFunctor 4 class Functor f where (<$>) :: (a -> b) -> f a -> f b 13 / 46

  24. The solution: IsoFunctor 4 class Functor f where (<$>) :: (a -> b) -> f a -> f b class IsoFunctor f where (<$>) :: Iso a b -> f a -> f b 13 / 46

  25. The important things about partial isos ◮ Unifying a functor requires both a → b and b → a 14 / 46

  26. The important things about partial isos ◮ Unifying a functor requires both a → b and b → a ◮ We unify both with a partial Iso, where these functions can fail 14 / 46

  27. The important things about partial isos ◮ Unifying a functor requires both a → b and b → a ◮ We unify both with a partial Iso, where these functions can fail ◮ We defined IsoFunctor (from partial isos to printer/parsers) 14 / 46

  28. Applicative class Applicative where (<*>) :: f (a -> b) -> f a -> f b 15 / 46

  29. Applicative class Applicative where (<*>) :: f (a -> b) -> f a -> f b class UnhelpfulIsoApplicative where (<*>) :: f (Iso a b) -> f a -> f b 15 / 46

  30. Applicative class Applicative where (<*>) :: f (a -> b) -> f a -> f b class UnhelpfulIsoApplicative where (<*>) :: f (Iso a b) -> f a -> f b type Printer a = a -> Doc instance UnhelpfulIsoApplicative Printer where (<*>) :: (Iso a b -> Doc) -> (a -> Doc) -> b -> Doc (f <*> g) b = error "how do I shot web?" 15 / 46

  31. Applicative class Functor f => Applicative f where (<*>) :: f (a -> b) -> f a -> f b 16 / 46

  32. Applicative class Functor f => Applicative f where (<*>) :: f (a -> b) -> f a -> f b class ProductFunctor f where infixr 6 <*> (<*>) :: f a -> f b -> f (a, b) 16 / 46

  33. Applicative class Functor f => Applicative f where (<*>) :: f (a -> b) -> f a -> f b class ProductFunctor f where infixr 6 <*> (<*>) :: f a -> f b -> f (a, b) instance ProductFunctor Printer where Printer p <*> Printer q = Printer $ \(x, y) -> liftM2 ( ++ ) (p x) (q y) 16 / 46

  34. Tuple trees for our data types nil :: Iso () (List a) cons :: Iso (a, List a) (List a) 17 / 46

  35. Tuple trees for our data types nil :: Iso () (List a) cons :: Iso (a, List a) (List a) data List a = Nil | Cons a (List a) defineIsomorphisms ''List 17 / 46

  36. The important things: ProductFunctor 18 / 46

  37. The important things: ProductFunctor ◮ Naively adapting Applicative leaves us with an uninhabitable type. 18 / 46

  38. The important things: ProductFunctor ◮ Naively adapting Applicative leaves us with an uninhabitable type. ◮ We use ProductFunctor, it has tuples instead of currying and associates right 18 / 46

  39. The important things: ProductFunctor ◮ Naively adapting Applicative leaves us with an uninhabitable type. ◮ We use ProductFunctor, it has tuples instead of currying and associates right ◮ <*> mushes tuples together one way, and takes them apart the other 18 / 46

  40. Almost done, Alternative 6 is trivial class Alternative where (<|>) :: f a -> f a -> f a 19 / 46

  41. We now have an abstract Syntax 7 class (IsoFunctor s, ProductFunctor s, Alternative s) => Syntax s where pure :: Eq a => a -> s a 20 / 46

  42. Invertible Syntax Descriptions: the punchline parseMany :: Parser a -> Parser (List a) parseMany p = const Nil <$> text "" <|> Cons <$> p printMany :: (a -> Doc) -> (List a -> Doc) printMany p list = case list of Nil -> text "" Cons x xs -> p x <> printMany p xs 21 / 46

  43. Invertible Syntax Descriptions: the punchline many :: Syntax s => s a -> s (List a) many p = nil <$> pure () <|> cons <$> p <*> many p 22 / 46

  44. Invertible Syntax Descriptions: summary 23 / 46

  45. Invertible Syntax Descriptions: summary ◮ Partial isos: composable building blocks for munging data 23 / 46

  46. Invertible Syntax Descriptions: summary ◮ Partial isos: composable building blocks for munging data ◮ IsoFunctor: to “lift” theses isos into concrete printers or parsers 23 / 46

  47. Invertible Syntax Descriptions: summary ◮ Partial isos: composable building blocks for munging data ◮ IsoFunctor: to “lift” theses isos into concrete printers or parsers ◮ ProductFunctor: to handle multiple fields and sequencing via tuples 23 / 46

  48. Invertible Syntax Descriptions: summary ◮ Partial isos: composable building blocks for munging data ◮ IsoFunctor: to “lift” theses isos into concrete printers or parsers ◮ ProductFunctor: to handle multiple fields and sequencing via tuples ◮ Syntax: to glue all these constraints together and add pure 23 / 46

  49. Let’s try it on enterprise JSON! Figure 2: We are now enterprise developers 24 / 46

  50. JsonBuilder/Parser IsoFunctor, simple! newtype JsonBuilder a = JsonBuilder { runBuilder :: a -> Maybe Value } newtype JsonParser a = JsonParser { runParser :: Value -> Maybe a } instance IsoFunctor JsonBuilder where (<$>) :: Iso a b -> JsonBuilder a -> JsonBuilder b i <$> JsonBuilder b = JsonBuilder $ unapply i >=> b instance IsoFunctor JsonParser where (<$>) :: Iso a b -> JsonParser a -> JsonParser b i <$> JsonParser p = JsonParser $ apply i <=< p 25 / 46

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend