{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE UndecidableInstances #-}
module H2JVM.Data.TypeMergingList (
TypeMergingList (..),
DataMergeable (..),
errorDifferentConstructors,
snoc,
toList,
toVector,
fromList,
)
where
import Data.Data
import Data.Vector (Vector)
import GHC.Stack
import Data.Vector qualified as V
import GHC.IsList qualified as L
import H2JVM.Internal.Pretty (Pretty (pretty))
newtype TypeMergingList a = TypeMergingList [a]
deriving (TypeMergingList a -> TypeMergingList a -> Bool
(TypeMergingList a -> TypeMergingList a -> Bool)
-> (TypeMergingList a -> TypeMergingList a -> Bool)
-> Eq (TypeMergingList a)
forall a. Eq a => TypeMergingList a -> TypeMergingList a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => TypeMergingList a -> TypeMergingList a -> Bool
== :: TypeMergingList a -> TypeMergingList a -> Bool
$c/= :: forall a. Eq a => TypeMergingList a -> TypeMergingList a -> Bool
/= :: TypeMergingList a -> TypeMergingList a -> Bool
Eq, Eq (TypeMergingList a)
Eq (TypeMergingList a) =>
(TypeMergingList a -> TypeMergingList a -> Ordering)
-> (TypeMergingList a -> TypeMergingList a -> Bool)
-> (TypeMergingList a -> TypeMergingList a -> Bool)
-> (TypeMergingList a -> TypeMergingList a -> Bool)
-> (TypeMergingList a -> TypeMergingList a -> Bool)
-> (TypeMergingList a -> TypeMergingList a -> TypeMergingList a)
-> (TypeMergingList a -> TypeMergingList a -> TypeMergingList a)
-> Ord (TypeMergingList a)
TypeMergingList a -> TypeMergingList a -> Bool
TypeMergingList a -> TypeMergingList a -> Ordering
TypeMergingList a -> TypeMergingList a -> TypeMergingList a
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (TypeMergingList a)
forall a. Ord a => TypeMergingList a -> TypeMergingList a -> Bool
forall a.
Ord a =>
TypeMergingList a -> TypeMergingList a -> Ordering
forall a.
Ord a =>
TypeMergingList a -> TypeMergingList a -> TypeMergingList a
$ccompare :: forall a.
Ord a =>
TypeMergingList a -> TypeMergingList a -> Ordering
compare :: TypeMergingList a -> TypeMergingList a -> Ordering
$c< :: forall a. Ord a => TypeMergingList a -> TypeMergingList a -> Bool
< :: TypeMergingList a -> TypeMergingList a -> Bool
$c<= :: forall a. Ord a => TypeMergingList a -> TypeMergingList a -> Bool
<= :: TypeMergingList a -> TypeMergingList a -> Bool
$c> :: forall a. Ord a => TypeMergingList a -> TypeMergingList a -> Bool
> :: TypeMergingList a -> TypeMergingList a -> Bool
$c>= :: forall a. Ord a => TypeMergingList a -> TypeMergingList a -> Bool
>= :: TypeMergingList a -> TypeMergingList a -> Bool
$cmax :: forall a.
Ord a =>
TypeMergingList a -> TypeMergingList a -> TypeMergingList a
max :: TypeMergingList a -> TypeMergingList a -> TypeMergingList a
$cmin :: forall a.
Ord a =>
TypeMergingList a -> TypeMergingList a -> TypeMergingList a
min :: TypeMergingList a -> TypeMergingList a -> TypeMergingList a
Ord, Int -> TypeMergingList a -> ShowS
[TypeMergingList a] -> ShowS
TypeMergingList a -> String
(Int -> TypeMergingList a -> ShowS)
-> (TypeMergingList a -> String)
-> ([TypeMergingList a] -> ShowS)
-> Show (TypeMergingList a)
forall a. Show a => Int -> TypeMergingList a -> ShowS
forall a. Show a => [TypeMergingList a] -> ShowS
forall a. Show a => TypeMergingList a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> TypeMergingList a -> ShowS
showsPrec :: Int -> TypeMergingList a -> ShowS
$cshow :: forall a. Show a => TypeMergingList a -> String
show :: TypeMergingList a -> String
$cshowList :: forall a. Show a => [TypeMergingList a] -> ShowS
showList :: [TypeMergingList a] -> ShowS
Show)
class Data a => DataMergeable a where
merge :: HasCallStack => a -> a -> a
errorDifferentConstructors :: (Data a, HasCallStack) => a -> a -> b
errorDifferentConstructors :: forall a b. (Data a, HasCallStack) => a -> a -> b
errorDifferentConstructors a
x a
y = String -> b
forall a. HasCallStack => String -> a
error (String -> b) -> String -> b
forall a b. (a -> b) -> a -> b
$ String
"Cannot merge values as they have different data constructors: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Constr -> String
showConstr (a -> Constr
forall a. Data a => a -> Constr
toConstr a
x) String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" and " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Constr -> String
showConstr (a -> Constr
forall a. Data a => a -> Constr
toConstr a
y)
instance {-# OVERLAPPABLE #-} (Data a, Semigroup a) => DataMergeable a where
merge :: HasCallStack => a -> a -> a
merge = a -> a -> a
forall a. Semigroup a => a -> a -> a
(<>)
snoc :: DataMergeable a => TypeMergingList a -> a -> TypeMergingList a
snoc :: forall a.
DataMergeable a =>
TypeMergingList a -> a -> TypeMergingList a
snoc (TypeMergingList []) a
x = [a] -> TypeMergingList a
forall a. [a] -> TypeMergingList a
TypeMergingList [a
x]
snoc (TypeMergingList (a
y : [a]
ys)) a
x
| a -> Constr
forall a. Data a => a -> Constr
toConstr a
y Constr -> Constr -> Bool
forall a. Eq a => a -> a -> Bool
== a -> Constr
forall a. Data a => a -> Constr
toConstr a
x = [a] -> TypeMergingList a
forall a. [a] -> TypeMergingList a
TypeMergingList ((a
y a -> a -> a
forall a. (DataMergeable a, HasCallStack) => a -> a -> a
`merge` a
x) a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
ys)
| Bool
otherwise = [a] -> TypeMergingList a
forall a. [a] -> TypeMergingList a
TypeMergingList (a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: a
y a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
ys)
append :: DataMergeable a => TypeMergingList a -> TypeMergingList a -> TypeMergingList a
append :: forall a.
DataMergeable a =>
TypeMergingList a -> TypeMergingList a -> TypeMergingList a
append TypeMergingList a
xs (TypeMergingList [a]
ys) = (a -> TypeMergingList a -> TypeMergingList a)
-> TypeMergingList a -> [a] -> TypeMergingList a
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((TypeMergingList a -> a -> TypeMergingList a)
-> a -> TypeMergingList a -> TypeMergingList a
forall a b c. (a -> b -> c) -> b -> a -> c
flip TypeMergingList a -> a -> TypeMergingList a
forall a.
DataMergeable a =>
TypeMergingList a -> a -> TypeMergingList a
snoc) TypeMergingList a
xs [a]
ys
fromList :: DataMergeable a => Data a => [a] -> TypeMergingList a
fromList :: forall a. (DataMergeable a, Data a) => [a] -> TypeMergingList a
fromList = (TypeMergingList a -> a -> TypeMergingList a)
-> TypeMergingList a -> [a] -> TypeMergingList a
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' TypeMergingList a -> a -> TypeMergingList a
forall a.
DataMergeable a =>
TypeMergingList a -> a -> TypeMergingList a
snoc ([a] -> TypeMergingList a
forall a. [a] -> TypeMergingList a
TypeMergingList [])
toList :: TypeMergingList a -> [a]
toList :: forall a. TypeMergingList a -> [a]
toList (TypeMergingList [a]
xs) = [a] -> [a]
forall a. [a] -> [a]
reverse [a]
xs
toVector :: TypeMergingList a -> Vector a
toVector :: forall a. TypeMergingList a -> Vector a
toVector (TypeMergingList [a]
xs) = [a] -> Vector a
forall a. [a] -> Vector a
V.fromList ([a] -> [a]
forall a. [a] -> [a]
reverse [a]
xs)
instance DataMergeable a => Semigroup (TypeMergingList a) where
<> :: TypeMergingList a -> TypeMergingList a -> TypeMergingList a
(<>) = TypeMergingList a -> TypeMergingList a -> TypeMergingList a
forall a.
DataMergeable a =>
TypeMergingList a -> TypeMergingList a -> TypeMergingList a
append
instance DataMergeable a => Monoid (TypeMergingList a) where
mempty :: TypeMergingList a
mempty = [a] -> TypeMergingList a
forall a. [a] -> TypeMergingList a
TypeMergingList []
instance DataMergeable a => L.IsList (TypeMergingList a) where
type Item (TypeMergingList a) = a
fromList :: [Item (TypeMergingList a)] -> TypeMergingList a
fromList = [a] -> TypeMergingList a
[Item (TypeMergingList a)] -> TypeMergingList a
forall a. (DataMergeable a, Data a) => [a] -> TypeMergingList a
fromList
toList :: TypeMergingList a -> [Item (TypeMergingList a)]
toList = TypeMergingList a -> [a]
TypeMergingList a -> [Item (TypeMergingList a)]
forall a. TypeMergingList a -> [a]
toList
instance Foldable TypeMergingList where
foldMap :: forall m a. Monoid m => (a -> m) -> TypeMergingList a -> m
foldMap a -> m
f (TypeMergingList [a]
xs) = (a -> m) -> [a] -> m
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> m
f ([a] -> [a]
forall a. [a] -> [a]
reverse [a]
xs)
instance Pretty a => Pretty (TypeMergingList a) where
pretty :: forall ann. TypeMergingList a -> Doc ann
pretty = (a -> Doc ann) -> [a] -> Doc ann
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> Doc ann
forall ann. a -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty ([a] -> Doc ann)
-> (TypeMergingList a -> [a]) -> TypeMergingList a -> Doc ann
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TypeMergingList a -> [a]
forall a. TypeMergingList a -> [a]
toList