Roundtrip Tutorial

Roundtrip Tutorial

DRAFT DRAFT DRAFT

Roundtrip allows the definition of bidirectional (de-)serialization specifications. The specification language is based on the ideas described in the paper Invertible Syntax Descriptions: Unifying Parsing and Pretty Printing by Tillmann Rendel and Klaus Ostermann, Haskell Symposium 2010 (online version).

Author: Stefan Wehr (wehr AT factisresearch DOT com)
Roundtrip on hackage:

Specification for parsing/printing expressions from strings

> {-# LANGUAGE OverloadedStrings, TemplateHaskell #-}
> module Spec where
>
> import Data.Char (isLetter, isDigit)
> import Text.Roundtrip
>
> data Expr = Var String
>           | Lit Int
>           | Plus Expr Expr
>             deriving (Show, Eq)
>
> $(defineIsomorphisms ''Expr)
>
> letter :: StringSyntax d => d Char
> letter =  token isLetter
>
> variable :: StringSyntax d => d String
> variable = cons <$> letter <*> many (letter <|> digit)
>
> digit :: StringSyntax d => d Char
> digit = token isDigit
>
> integer :: StringSyntax d => d Int
> integer = signedIntIso <$> optionalBool (char '-') <*> (readShowIso <$> many1 digit)
>     where
>       signedIntIso :: Iso (Bool, Int) Int
>       signedIntIso = let f (True, i) = Just (-i)
>                          f (False, i) = Just i
>                          g i = Just (i < 0, abs i)
>                      in unsafeMakeIso f g
>
> pExpr :: StringSyntax d => d Expr
> pExpr = var  <$> variable
>     <|> lit  <$> integer
>     <|> plus <$> (char '(' *> pExpr <*>
>                   char '+' *> pExpr <* char ')')

Specification for parsing/printing expressions from an XML tree

> {-
> <plus>
>   <var name="foo"/>
>   <lit value="123"/>
> </plus>
> -}
>
> xmlVariable :: XmlSyntax d => d String
> xmlVariable = xmlElem "var" (xmlAttr "name" textStringIso)
>
> xmlInteger :: XmlSyntax d => d Int
> xmlInteger = xmlElem "lit" (xmlAttr "value" readShowTextIso)
>
> pXmlExpr :: XmlSyntax d => d Expr
> pXmlExpr = var  <$> xmlVariable
>        <|> lit  <$> xmlInteger
>        <|> plus <$> xmlElem "plus" (pXmlExpr <*> pXmlExpr)
The Impl module shows these specifications in action.