module Dhall.Extra
( RecordBuilder
, keyValue
, makeRecord
, makeUnion
, validateType
, sortExpr
)
where
import Control.Applicative ( Const(..) )
import Control.Monad ( join )
import Control.Monad.Trans.Reader ( Reader, reader, runReader )
import Data.Functor.Compose ( Compose(..) )
import Data.Functor.Product ( Product(..) )
import Data.Hashable ( Hashable )
import Data.List ( sortBy )
import Data.Ord ( comparing )
import qualified Data.HashMap.Strict.InsOrd as Map
import qualified Data.Text.Lazy as LazyText
import qualified Dhall
import qualified Dhall.Core as Dhall ( Expr )
import qualified Dhall.Core as Expr ( Expr(..) )
import qualified Dhall.Parser
import qualified Dhall.TypeCheck
newtype RecordBuilder a =
RecordBuilder
( Product
( Const
( Map.InsOrdHashMap
LazyText.Text
( Dhall.Expr Dhall.Parser.Src Dhall.TypeCheck.X )
)
)
( Compose
( Reader
( Dhall.Expr Dhall.Parser.Src Dhall.TypeCheck.X )
)
Maybe
)
a
)
deriving (Functor, Applicative)
makeRecord :: RecordBuilder a -> Dhall.Type a
makeRecord ( RecordBuilder ( Pair ( Const fields ) ( Compose extractF ) ) ) =
let
extract =
runReader extractF
expected =
sortExpr ( Expr.Record fields )
in Dhall.Type { .. }
keyValue :: LazyText.Text -> Dhall.Type a -> RecordBuilder a
keyValue key valueType =
let
extract expr = do
Expr.RecordLit fields <-
return expr
Map.lookup key fields >>= Dhall.extract valueType
in
RecordBuilder
( Pair
( Const ( Map.singleton key ( Dhall.expected valueType ) ) )
( Compose ( reader extract ) )
)
makeUnion :: Map.InsOrdHashMap LazyText.Text ( Dhall.Type a ) -> Dhall.Type a
makeUnion alts =
let
extract expr = do
Expr.UnionLit ctor v _ <-
return expr
t <-
Map.lookup ctor alts
Dhall.extract t v
expected =
sortExpr ( Expr.Union ( Dhall.expected <$> alts ) )
in Dhall.Type { .. }
validateType :: Dhall.Type ( Maybe a ) -> Dhall.Type a
validateType a =
a { Dhall.extract = join . Dhall.extract a }
sortInsOrdHashMap :: ( Hashable k, Ord k ) => Map.InsOrdHashMap k v -> Map.InsOrdHashMap k v
sortInsOrdHashMap =
Map.fromList . sortBy ( comparing fst ) . Map.toList
sortExpr :: Dhall.Expr s a -> Dhall.Expr s a
sortExpr = \case
Expr.RecordLit r ->
Expr.RecordLit ( sortInsOrdHashMap r )
Expr.Record r ->
Expr.Record ( sortInsOrdHashMap r )
Expr.Union r ->
Expr.Union ( sortInsOrdHashMap r )
e ->
e