streamly-0.10.0: test/Streamly/Test/Data/Serialize/TH.hs
{-# LANGUAGE TemplateHaskell #-}
-- |
-- Module : Streamly.Test.Data.Serialize.TH
-- Copyright : (c) 2022 Composewell technologies
-- License : BSD-3-Clause
-- Maintainer : streamly@composewell.com
-- Stability : experimental
-- Portability : GHC
module Streamly.Test.Data.Serialize.TH (genDatatype) where
--------------------------------------------------------------------------------
-- Imports
--------------------------------------------------------------------------------
import Language.Haskell.TH
import Test.QuickCheck.Arbitrary (Arbitrary(..))
import Test.QuickCheck.Gen (oneof)
--------------------------------------------------------------------------------
-- Generated types
--------------------------------------------------------------------------------
genDatatype :: String -> Int -> Q [Dec]
genDatatype tyName numCons =
sequence
([ dataD
(pure [])
(mkName tyName)
[]
Nothing
(mkCon <$> [0 .. (numCons - 1)])
[derivClause Nothing [conT ''Eq, conT ''Show]]
, instanceD
(pure [])
(appT (conT ''Arbitrary) (conT (mkName tyName)))
[ funD
'arbitrary
[ clause
[]
(normalB
(appE
(varE 'oneof)
(listE
(mkArbitraryExp <$>
[0 .. (numCons - 1)]))))
[]
]
]
])
where
fieldTypeChoices =
[ conT ''Int
, conT ''Char
, conT ''String
, appT listT (conT ''Int)
, appT listT (conT ''String)
, appT listT (appT listT (conT ''Int))
, appT listT (appT listT (conT ''String))
]
chooseCycle i xs = xs !! (i `mod` length xs)
mkArbitraryExp i =
foldl
(\b a -> [|$(b) <*> $(a)|])
[|pure $(conE (mkName ("Constructor" ++ show i)))|]
(replicate i (varE 'arbitrary))
mkCon i =
normalC
(mkName ("Constructor" ++ show i))
(mkField <$> [0..(i - 1)])
mkField i =
bangType
(bang noSourceUnpackedness noSourceStrictness)
(chooseCycle i fieldTypeChoices)