{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveLift #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskellQuotes #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE NoImplicitPrelude #-} module Data.Mergeable.MergeMap ( MergeMap, toNonEmpty, partition, ) where import Control.Monad.Except (MonadError (..)) import qualified Data.List as L import qualified Data.List.NonEmpty as NE (partition) import qualified Data.List.NonEmpty as NM import Data.Mergeable.Internal.Merge ( Merge (..), recursiveMerge, ) import Data.Mergeable.IsMap (FromList (..), IsMap (..)) import Language.Haskell.TH.Syntax (Lift (..)) import Relude hiding (fromList) partition :: (a -> Bool) -> MergeMap dups k a -> (Maybe (MergeMap dups k a), Maybe (MergeMap dups k a)) partition f (MergeMap xs) = case NE.partition (f . snd) xs of ([], _) -> (Nothing, Just (MergeMap xs)) (_, []) -> (Just (MergeMap xs), Nothing) (a : as, b : bs) -> (Just (MergeMap (a :| as)), Just (MergeMap (b :| bs))) newtype MergeMap (dups :: Bool) k a = MergeMap { unpack :: NonEmpty (k, a) } deriving ( Show, Eq, Functor, Foldable, Traversable ) instance (Lift a, Lift k) => Lift (MergeMap dups k a) where lift (MergeMap (x :| xs)) = [|MergeMap (x :| xs)|] #if MIN_VERSION_template_haskell(2,16,0) liftTyped (MergeMap (x :| xs)) = [|| MergeMap (x :| xs) ||] #endif instance (Hashable k, Eq k) => IsMap k (MergeMap dups k) where unsafeFromList (x : xs) = MergeMap (x :| xs) unsafeFromList [] = error "empty selection sets are not supported." singleton k x = MergeMap ((k, x) :| []) lookup key (MergeMap (x :| xs)) = L.lookup key (x : xs) toAssoc (MergeMap (x :| xs)) = x : xs instance ( Monad m, Eq a, Merge m a, Hashable k, Eq k ) => Merge m (MergeMap 'False k a) where merge (MergeMap x) (MergeMap y) = resolveMergeable (x <> y) instance Monad m => Merge m (MergeMap 'True k a) where merge (MergeMap x) (MergeMap y) = pure $ MergeMap $ x <> y resolveMergeable :: ( Monad m, Eq a, Merge m a, Hashable k, Eq k ) => NonEmpty (k, a) -> m (MergeMap dups k a) resolveMergeable (x :| xs) = recursiveMerge (MergeMap . NM.fromList) (x : xs) toNonEmpty :: (IsString e, MonadError e f) => [a] -> f (NonEmpty a) toNonEmpty [] = throwError $ fromString "empty selection sets are not supported." toNonEmpty (x : xs) = pure (x :| xs) instance ( Hashable k, Eq k, Eq a, IsString e, MonadError e m, Merge m a ) => FromList m (MergeMap 'False) k a where fromList = resolveMergeable <=< toNonEmpty instance ( IsString e, MonadError e m ) => FromList m (MergeMap 'True) k a where fromList = fmap MergeMap . toNonEmpty