feat: merge objects in unions
This commit is contained in:
parent
0d7c9651b0
commit
4f9cec2d51
1 changed files with 17 additions and 5 deletions
|
@ -2,7 +2,7 @@
|
||||||
{-# LANGUAGE LambdaCase #-}
|
{-# LANGUAGE LambdaCase #-}
|
||||||
{-# LANGUAGE DerivingVia #-}
|
{-# LANGUAGE DerivingVia #-}
|
||||||
{-# LANGUAGE DeriveGeneric #-}
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
module Language.Json.Type (infer, Type(..)) where
|
module Language.Json.Type (infer, Type(..), isObject) where
|
||||||
import Data.Map.Strict (Map)
|
import Data.Map.Strict (Map)
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import Data.Set (Set)
|
import Data.Set (Set)
|
||||||
|
@ -38,15 +38,27 @@ instance Semigroup Type where
|
||||||
mergeMatched = (Map.zipWithMatched $ const (<>)) -- merge keys present in both maps
|
mergeMatched = (Map.zipWithMatched $ const (<>)) -- merge keys present in both maps
|
||||||
unionNull = (Map.mapMissing $ const (<> Null)) -- mark keys missing in either map as nullable
|
unionNull = (Map.mapMissing $ const (<> Null)) -- mark keys missing in either map as nullable
|
||||||
in Object $ Map.merge unionNull unionNull mergeMatched fieldsA fieldsB
|
in Object $ Map.merge unionNull unionNull mergeMatched fieldsA fieldsB
|
||||||
(Union typesA, Union typesB) -> Union $ Set.union typesA typesB
|
(Union typesA, Union typesB) -> Union . mergeUnionObjects $ Set.union typesA typesB
|
||||||
(Union typesA, _) -> Union $ Set.insert b typesA
|
(Union typesA, _) -> Union . mergeUnionObjects $ Set.insert b typesA
|
||||||
(_, Union typesB) -> Union $ Set.insert a typesB
|
(_, Union typesB) -> Union . mergeUnionObjects $ Set.insert a typesB
|
||||||
_ -> Union $ Set.fromList [a, b]
|
_ -> Union . mergeUnionObjects $ Set.fromList [a, b]
|
||||||
|
|
||||||
instance Monoid Type where
|
instance Monoid Type where
|
||||||
mempty :: Type
|
mempty :: Type
|
||||||
mempty = All
|
mempty = All
|
||||||
|
|
||||||
|
mergeUnionObjects :: Set Type -> Set Type
|
||||||
|
mergeUnionObjects set = let
|
||||||
|
(objects, rest) = Set.partition isObject set
|
||||||
|
in if Set.null objects
|
||||||
|
then rest
|
||||||
|
else Set.insert (Set.foldl (<>) mempty objects) rest
|
||||||
|
|
||||||
|
isObject :: Type -> Bool
|
||||||
|
isObject = \case
|
||||||
|
Object _ -> True
|
||||||
|
_ -> False
|
||||||
|
|
||||||
infer :: Json.Value -> Type
|
infer :: Json.Value -> Type
|
||||||
infer = \case
|
infer = \case
|
||||||
Value.Null -> Null
|
Value.Null -> Null
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue