{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
module Data.Functor.Misc
(
Const2 (..)
, unConst2
, dmapToMap
, dmapToIntMap
, dmapToMapWith
, mapToDMap
, weakenDMapWith
, WrapArg (..)
, mapWithFunctorToDMap
, intMapWithFunctorToDMap
, mapKeyValuePairsMonotonic
, combineDMapsWithKey
, EitherTag (..)
, dmapToThese
, eitherToDSum
, dsumToEither
, ComposeMaybe (..)
) where
import Control.Applicative ((<$>))
import Data.Dependent.Map (DMap)
import qualified Data.Dependent.Map as DMap
import Data.Dependent.Sum
import Data.Functor.Identity
import Data.GADT.Compare
import Data.GADT.Show
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Some (Some(Some))
import Data.These
import Data.Type.Equality ((:~:)(Refl))
import Data.Typeable hiding (Refl)
data Const2 :: * -> x -> x -> * where
Const2 :: k -> Const2 k v v
deriving (Typeable)
unConst2 :: Const2 k v v' -> k
unConst2 (Const2 k) = k
deriving instance Eq k => Eq (Const2 k v v')
deriving instance Ord k => Ord (Const2 k v v')
deriving instance Show k => Show (Const2 k v v')
deriving instance Read k => Read (Const2 k v v)
instance Show k => GShow (Const2 k v) where
gshowsPrec n x@(Const2 _) = showsPrec n x
instance Eq k => GEq (Const2 k v) where
geq (Const2 a) (Const2 b) =
if a == b
then Just Refl
else Nothing
instance Ord k => GCompare (Const2 k v) where
gcompare (Const2 a) (Const2 b) = case compare a b of
LT -> GLT
EQ -> GEQ
GT -> GGT
dmapToMap :: DMap (Const2 k v) Identity -> Map k v
dmapToMap = Map.fromDistinctAscList . map (\(Const2 k :=> Identity v) -> (k, v)) . DMap.toAscList
dmapToIntMap :: DMap (Const2 IntMap.Key v) Identity -> IntMap v
dmapToIntMap = IntMap.fromDistinctAscList . map (\(Const2 k :=> Identity v) -> (k, v)) . DMap.toAscList
dmapToMapWith :: (f v -> v') -> DMap (Const2 k v) f -> Map k v'
dmapToMapWith f = Map.fromDistinctAscList . map (\(Const2 k :=> v) -> (k, f v)) . DMap.toAscList
mapToDMap :: Map k v -> DMap (Const2 k v) Identity
mapToDMap = DMap.fromDistinctAscList . map (\(k, v) -> Const2 k :=> Identity v) . Map.toAscList
mapWithFunctorToDMap :: Map k (f v) -> DMap (Const2 k v) f
mapWithFunctorToDMap = DMap.fromDistinctAscList . map (\(k, v) -> Const2 k :=> v) . Map.toAscList
intMapWithFunctorToDMap :: IntMap (f v) -> DMap (Const2 IntMap.Key v) f
intMapWithFunctorToDMap = DMap.fromDistinctAscList . map (\(k, v) -> Const2 k :=> v) . IntMap.toAscList
weakenDMapWith :: (forall a. v a -> v') -> DMap k v -> Map (Some k) v'
weakenDMapWith f = Map.fromDistinctAscList . map (\(k :=> v) -> (Some k, f v)) . DMap.toAscList
data WrapArg :: (k -> *) -> (k -> *) -> * -> * where
WrapArg :: f a -> WrapArg g f (g a)
deriving instance Eq (f a) => Eq (WrapArg g f (g' a))
deriving instance Ord (f a) => Ord (WrapArg g f (g' a))
deriving instance Show (f a) => Show (WrapArg g f (g' a))
deriving instance Read (f a) => Read (WrapArg g f (g a))
instance GEq f => GEq (WrapArg g f) where
geq (WrapArg a) (WrapArg b) = (\Refl -> Refl) <$> geq a b
instance GCompare f => GCompare (WrapArg g f) where
gcompare (WrapArg a) (WrapArg b) = case gcompare a b of
GLT -> GLT
GEQ -> GEQ
GGT -> GGT
mapKeyValuePairsMonotonic :: (DSum k v -> DSum k' v') -> DMap k v -> DMap k' v'
mapKeyValuePairsMonotonic f = DMap.fromDistinctAscList . map f . DMap.toAscList
{-# INLINE combineDMapsWithKey #-}
combineDMapsWithKey :: forall f g h i.
GCompare f
=> (forall a. f a -> These (g a) (h a) -> i a)
-> DMap f g
-> DMap f h
-> DMap f i
combineDMapsWithKey f mg mh = DMap.fromList $ go (DMap.toList mg) (DMap.toList mh)
where go :: [DSum f g] -> [DSum f h] -> [DSum f i]
go [] hs = map (\(hk :=> hv) -> hk :=> f hk (That hv)) hs
go gs [] = map (\(gk :=> gv) -> gk :=> f gk (This gv)) gs
go gs@((gk :=> gv) : gs') hs@((hk :=> hv) : hs') = case gk `gcompare` hk of
GLT -> (gk :=> f gk (This gv)) : go gs' hs
GEQ -> (gk :=> f gk (These gv hv)) : go gs' hs'
GGT -> (hk :=> f hk (That hv)) : go gs hs'
dmapToThese :: DMap (EitherTag a b) Identity -> Maybe (These a b)
dmapToThese m = case (DMap.lookup LeftTag m, DMap.lookup RightTag m) of
(Nothing, Nothing) -> Nothing
(Just (Identity a), Nothing) -> Just $ This a
(Nothing, Just (Identity b)) -> Just $ That b
(Just (Identity a), Just (Identity b)) -> Just $ These a b
data EitherTag l r a where
LeftTag :: EitherTag l r l
RightTag :: EitherTag l r r
deriving (Typeable)
deriving instance Show (EitherTag l r a)
deriving instance Eq (EitherTag l r a)
deriving instance Ord (EitherTag l r a)
instance GEq (EitherTag l r) where
geq a b = case (a, b) of
(LeftTag, LeftTag) -> Just Refl
(RightTag, RightTag) -> Just Refl
_ -> Nothing
instance GCompare (EitherTag l r) where
gcompare a b = case (a, b) of
(LeftTag, LeftTag) -> GEQ
(LeftTag, RightTag) -> GLT
(RightTag, LeftTag) -> GGT
(RightTag, RightTag) -> GEQ
instance GShow (EitherTag l r) where
gshowsPrec _ a = case a of
LeftTag -> showString "LeftTag"
RightTag -> showString "RightTag"
eitherToDSum :: Either a b -> DSum (EitherTag a b) Identity
eitherToDSum = \case
Left a -> (LeftTag :=> Identity a)
Right b -> (RightTag :=> Identity b)
dsumToEither :: DSum (EitherTag a b) Identity -> Either a b
dsumToEither = \case
(LeftTag :=> Identity a) -> Left a
(RightTag :=> Identity b) -> Right b
newtype ComposeMaybe f a =
ComposeMaybe { getComposeMaybe :: Maybe (f a) } deriving (Show, Eq, Ord)
deriving instance Functor f => Functor (ComposeMaybe f)