{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
-- TH does not generate signatures
{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
module Main where
import Control.Isomorphism.Partial
import Prelude hiding ((<$>), (*>), (<*>))
import Data.Aeson
import qualified Data.ByteString.Lazy.Char8 as L
import Data.Monoid
import Data.Text (Text)
import Text.Roundtrip.Classes
import Text.Roundtrip.Combinators
import Data.Aeson.Roundtrip
-- | A silly example
data Invoice
= Unpaid Integer [Bool]
| Paid Double
deriving (Show)
defineIsomorphisms ''Invoice
-- | An example of nesting syntaxes
data Account = Account Text [Invoice]
deriving Show
defineIsomorphisms ''Account
-- | A syntax is an abstract representation of the structure of a document.
--
-- It is built up by composing partial isomorphisms which have been
-- 'IsoFunctor' fmapped onto the 'JsonSyntax' value primitive.
invoiceSyntax :: JsonSyntax s => s Invoice
invoiceSyntax =
-- unpaid is an iso from Invoice to (Integer, [Bool])
unpaid
-- Ignore "paid", but make sure it's set to False
<$> jsonField "paid" (jsonBool `is` False)
*> jsonField "bar" jsonIntegral
<*> jsonField "baz" (many jsonBool)
-- If the s Invoice above failed, try the one for paid
<|> paid
<$> jsonField "paid" (jsonBool `is` True)
*> jsonField "bar" jsonRealFloat
-- | An example of nesting syntax definitions
accountSyntax :: JsonSyntax s => s Account
accountSyntax = account
<$> jsonField "name" jsonString
<*> jsonField "invoices" (many invoiceSyntax)
-- | A really bad acceptance test
main :: IO ()
main = do
putStrLn "FIELDS"
putStrLn "\tUNPARSE"
let Right x = runBuilder invoiceSyntax $ Unpaid 40 [False, True, False]
let Right y = runBuilder invoiceSyntax $ Paid 42
L.putStrLn $ "\t" <> encode x
L.putStrLn $ "\t" <> encode y
putStrLn "\n\tPARSE"
putStrLn $ "\t" <> show (runParser invoiceSyntax x)
putStrLn $ "\t" <> show (runParser invoiceSyntax y)
putStrLn "\n\nLISTS"
putStrLn "\tUNPARSE"
let Right z1 = runBuilder accountSyntax $ Account "Foo"
[ Unpaid 44 [True]
, Paid 46
]
L.putStrLn $ "\t" <> encode z1
let Right z2 = runBuilder accountSyntax $ Account "Bar" []
L.putStrLn $ "\t" <> encode z2
putStrLn "\n\tPARSE"
putStrLn $ "\t" <> show (runParser accountSyntax z1)
putStrLn $ "\t" <> show (runParser accountSyntax z2)