{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-deprecations #-}
module Data.SOP.NS
(
NS(..)
, SOP(..)
, unSOP
, Injection
, injections
, shift
, shiftInjection
, apInjs_NP
, apInjs'_NP
, apInjs_POP
, apInjs'_POP
, unZ
, index_NS
, index_SOP
, Ejection
, ejections
, shiftEjection
, ap_NS
, ap_SOP
, liftA_NS
, liftA_SOP
, liftA2_NS
, liftA2_SOP
, cliftA_NS
, cliftA_SOP
, cliftA2_NS
, cliftA2_SOP
, map_NS
, map_SOP
, cmap_NS
, cmap_SOP
, cliftA2'_NS
, compare_NS
, ccompare_NS
, compare_SOP
, ccompare_SOP
, collapse_NS
, collapse_SOP
, ctraverse__NS
, ctraverse__SOP
, traverse__NS
, traverse__SOP
, cfoldMap_NS
, cfoldMap_SOP
, sequence'_NS
, sequence'_SOP
, sequence_NS
, sequence_SOP
, ctraverse'_NS
, ctraverse'_SOP
, traverse'_NS
, traverse'_SOP
, ctraverse_NS
, ctraverse_SOP
, cata_NS
, ccata_NS
, ana_NS
, cana_NS
, expand_NS
, cexpand_NS
, expand_SOP
, cexpand_SOP
, trans_NS
, trans_SOP
, coerce_NS
, coerce_SOP
, fromI_NS
, fromI_SOP
, toI_NS
, toI_SOP
) where
import Data.Coerce
import Data.Kind (Type)
import Data.Proxy (Proxy (..))
import Unsafe.Coerce
import Control.DeepSeq (NFData(..))
import Data.SOP.BasicFunctors
import Data.SOP.Classes
import Data.SOP.Constraint
import Data.SOP.NP
import Data.SOP.Sing
data NS :: (k -> Type) -> [k] -> Type where
Z :: f x -> NS f (x ': xs)
S :: NS f xs -> NS f (x ': xs)
deriving instance All (Show `Compose` f) xs => Show (NS f xs)
deriving instance All (Eq `Compose` f) xs => Eq (NS f xs)
deriving instance (All (Eq `Compose` f) xs, All (Ord `Compose` f) xs) => Ord (NS f xs)
instance All (NFData `Compose` f) xs => NFData (NS f xs) where
rnf (Z x) = rnf x
rnf (S xs) = rnf xs
type Ejection (f :: k -> Type) (xs :: [k]) = K (NS f xs) -.-> Maybe :.: f
ejections :: forall xs f . SListI xs => NP (Ejection f xs) xs
ejections = case sList :: SList xs of
SNil -> Nil
SCons ->
fn (Comp . (\ns -> case ns of Z fx -> Just fx; S _ -> Nothing) . unK) :*
liftA_NP shiftEjection ejections
shiftEjection :: forall f x xs a . Ejection f xs a -> Ejection f (x ': xs) a
shiftEjection (Fn f) = Fn $ (\ns -> case ns of Z _ -> Comp Nothing; S s -> f (K s)) . unK
unZ :: NS f '[x] -> f x
unZ (Z x) = x
unZ (S x) = case x of {}
index_NS :: forall f xs . NS f xs -> Int
index_NS = go 0
where
go :: forall ys . Int -> NS f ys -> Int
go !acc (Z _) = acc
go !acc (S x) = go (acc + 1) x
instance HIndex NS where
hindex = index_NS
newtype SOP (f :: (k -> Type)) (xss :: [[k]]) = SOP (NS (NP f) xss)
deriving instance (Show (NS (NP f) xss)) => Show (SOP f xss)
deriving instance (Eq (NS (NP f) xss)) => Eq (SOP f xss)
deriving instance (Ord (NS (NP f) xss)) => Ord (SOP f xss)
instance (NFData (NS (NP f) xss)) => NFData (SOP f xss) where
rnf (SOP xss) = rnf xss
unSOP :: SOP f xss -> NS (NP f) xss
unSOP (SOP xss) = xss
type instance AllN NS c = All c
type instance AllN SOP c = All2 c
index_SOP :: SOP f xs -> Int
index_SOP = index_NS . unSOP
instance HIndex SOP where
hindex = index_SOP
type Injection (f :: k -> Type) (xs :: [k]) = f -.-> K (NS f xs)
injections :: forall xs f. SListI xs => NP (Injection f xs) xs
injections = case sList :: SList xs of
SNil -> Nil
SCons -> fn (K . Z) :* liftA_NP shiftInjection injections
shiftInjection :: Injection f xs a -> Injection f (x ': xs) a
shiftInjection (Fn f) = Fn $ K . S . unK . f
{-# DEPRECATED shift "Use 'shiftInjection' instead." #-}
shift :: Injection f xs a -> Injection f (x ': xs) a
shift = shiftInjection
apInjs_NP :: SListI xs => NP f xs -> [NS f xs]
apInjs_NP = hcollapse . apInjs'_NP
apInjs'_NP :: SListI xs => NP f xs -> NP (K (NS f xs)) xs
apInjs'_NP = hap injections
apInjs_POP :: SListI xss => POP f xss -> [SOP f xss]
apInjs_POP = map SOP . apInjs_NP . unPOP
apInjs'_POP :: SListI xss => POP f xss -> NP (K (SOP f xss)) xss
apInjs'_POP = hmap (K . SOP . unK) . hap injections . unPOP
type instance UnProd NP = NS
type instance UnProd POP = SOP
instance HApInjs NS where
hapInjs = apInjs_NP
instance HApInjs SOP where
hapInjs = apInjs_POP
ap_NS :: NP (f -.-> g) xs -> NS f xs -> NS g xs
ap_NS (Fn f :* _) (Z x) = Z (f x)
ap_NS (_ :* fs) (S xs) = S (ap_NS fs xs)
ap_NS Nil x = case x of {}
ap_SOP :: POP (f -.-> g) xss -> SOP f xss -> SOP g xss
ap_SOP (POP fss') (SOP xss') = SOP (go fss' xss')
where
go :: NP (NP (f -.-> g)) xss -> NS (NP f) xss -> NS (NP g) xss
go (fs :* _ ) (Z xs ) = Z (ap_NP fs xs )
go (_ :* fss) (S xss) = S (go fss xss)
go Nil x = case x of {}
_ap_SOP_spec :: SListI xss => POP (t -.-> f) xss -> SOP t xss -> SOP f xss
_ap_SOP_spec (POP fs) (SOP xs) = SOP (liftA2_NS ap_NP fs xs)
type instance Same NS = NS
type instance Same SOP = SOP
type instance Prod NS = NP
type instance Prod SOP = POP
type instance SListIN NS = SListI
type instance SListIN SOP = SListI2
instance HAp NS where hap = ap_NS
instance HAp SOP where hap = ap_SOP
liftA_NS :: SListI xs => (forall a. f a -> g a) -> NS f xs -> NS g xs
liftA_SOP :: All SListI xss => (forall a. f a -> g a) -> SOP f xss -> SOP g xss
liftA_NS = hliftA
liftA_SOP = hliftA
liftA2_NS :: SListI xs => (forall a. f a -> g a -> h a) -> NP f xs -> NS g xs -> NS h xs
liftA2_SOP :: All SListI xss => (forall a. f a -> g a -> h a) -> POP f xss -> SOP g xss -> SOP h xss
liftA2_NS = hliftA2
liftA2_SOP = hliftA2
map_NS :: SListI xs => (forall a. f a -> g a) -> NS f xs -> NS g xs
map_SOP :: All SListI xss => (forall a. f a -> g a) -> SOP f xss -> SOP g xss
map_NS = hmap
map_SOP = hmap
cliftA_NS :: All c xs => proxy c -> (forall a. c a => f a -> g a) -> NS f xs -> NS g xs
cliftA_SOP :: All2 c xss => proxy c -> (forall a. c a => f a -> g a) -> SOP f xss -> SOP g xss
cliftA_NS = hcliftA
cliftA_SOP = hcliftA
cliftA2_NS :: All c xs => proxy c -> (forall a. c a => f a -> g a -> h a) -> NP f xs -> NS g xs -> NS h xs
cliftA2_SOP :: All2 c xss => proxy c -> (forall a. c a => f a -> g a -> h a) -> POP f xss -> SOP g xss -> SOP h xss
cliftA2_NS = hcliftA2
cliftA2_SOP = hcliftA2
cmap_NS :: All c xs => proxy c -> (forall a. c a => f a -> g a) -> NS f xs -> NS g xs
cmap_SOP :: All2 c xss => proxy c -> (forall a. c a => f a -> g a) -> SOP f xss -> SOP g xss
cmap_NS = hcmap
cmap_SOP = hcmap
{-# DEPRECATED cliftA2'_NS "Use 'cliftA2_NS' instead." #-}
cliftA2'_NS :: All2 c xss => proxy c -> (forall xs. All c xs => f xs -> g xs -> h xs) -> NP f xss -> NS g xss -> NS h xss
cliftA2'_NS = hcliftA2'
compare_NS ::
forall r f g xs .
r
-> (forall x . f x -> g x -> r)
-> r
-> NS f xs -> NS g xs
-> r
compare_NS lt eq gt = go
where
go :: forall ys . NS f ys -> NS g ys -> r
go (Z x) (Z y) = eq x y
go (Z _) (S _) = lt
go (S _) (Z _) = gt
go (S xs) (S ys) = go xs ys
ccompare_NS ::
forall c proxy r f g xs .
(All c xs)
=> proxy c
-> r
-> (forall x . c x => f x -> g x -> r)
-> r
-> NS f xs -> NS g xs
-> r
ccompare_NS _ lt eq gt = go
where
go :: forall ys . (All c ys) => NS f ys -> NS g ys -> r
go (Z x) (Z y) = eq x y
go (Z _) (S _) = lt
go (S _) (Z _) = gt
go (S xs) (S ys) = go xs ys
compare_SOP ::
forall r f g xss .
r
-> (forall xs . NP f xs -> NP g xs -> r)
-> r
-> SOP f xss -> SOP g xss
-> r
compare_SOP lt eq gt (SOP xs) (SOP ys) =
compare_NS lt eq gt xs ys
ccompare_SOP ::
forall c proxy r f g xss .
(All2 c xss)
=> proxy c
-> r
-> (forall xs . All c xs => NP f xs -> NP g xs -> r)
-> r
-> SOP f xss -> SOP g xss
-> r
ccompare_SOP p lt eq gt (SOP xs) (SOP ys) =
ccompare_NS (allP p) lt eq gt xs ys
collapse_NS :: NS (K a) xs -> a
collapse_SOP :: SListI xss => SOP (K a) xss -> [a]
collapse_NS (Z (K x)) = x
collapse_NS (S xs) = collapse_NS xs
collapse_SOP = collapse_NS . hliftA (K . collapse_NP) . unSOP
type instance CollapseTo NS a = a
type instance CollapseTo SOP a = [a]
instance HCollapse NS where hcollapse = collapse_NS
instance HCollapse SOP where hcollapse = collapse_SOP
ctraverse__NS ::
forall c proxy xs f g. (All c xs)
=> proxy c -> (forall a. c a => f a -> g ()) -> NS f xs -> g ()
ctraverse__NS _ f = go
where
go :: All c ys => NS f ys -> g ()
go (Z x) = f x
go (S xs) = go xs
traverse__NS ::
forall xs f g. (SListI xs)
=> (forall a. f a -> g ()) -> NS f xs -> g ()
traverse__NS f = go
where
go :: NS f ys -> g ()
go (Z x) = f x
go (S xs) = go xs
ctraverse__SOP ::
forall c proxy xss f g. (All2 c xss, Applicative g)
=> proxy c -> (forall a. c a => f a -> g ()) -> SOP f xss -> g ()
ctraverse__SOP p f = ctraverse__NS (allP p) (ctraverse__NP p f) . unSOP
traverse__SOP ::
forall xss f g. (SListI2 xss, Applicative g)
=> (forall a. f a -> g ()) -> SOP f xss -> g ()
traverse__SOP f =
ctraverse__SOP topP f
{-# INLINE traverse__SOP #-}
topP :: Proxy Top
topP = Proxy
instance HTraverse_ NS where
hctraverse_ = ctraverse__NS
htraverse_ = traverse__NS
instance HTraverse_ SOP where
hctraverse_ = ctraverse__SOP
htraverse_ = traverse__SOP
cfoldMap_NS ::
forall c proxy f xs m. (All c xs)
=> proxy c -> (forall a. c a => f a -> m) -> NS f xs -> m
cfoldMap_NS _ f = go
where
go :: All c ys => NS f ys -> m
go (Z x) = f x
go (S xs) = go xs
cfoldMap_SOP :: (All2 c xs, Monoid m) => proxy c -> (forall a. c a => f a -> m) -> SOP f xs -> m
cfoldMap_SOP = hcfoldMap
sequence'_NS :: Applicative f => NS (f :.: g) xs -> f (NS g xs)
sequence'_NS (Z mx) = Z <$> unComp mx
sequence'_NS (S mxs) = S <$> sequence'_NS mxs
sequence'_SOP :: (SListI xss, Applicative f) => SOP (f :.: g) xss -> f (SOP g xss)
sequence'_SOP = fmap SOP . sequence'_NS . hliftA (Comp . sequence'_NP) . unSOP
ctraverse'_NS ::
forall c proxy xs f f' g. (All c xs, Functor g)
=> proxy c -> (forall a. c a => f a -> g (f' a)) -> NS f xs -> g (NS f' xs)
ctraverse'_NS _ f = go where
go :: All c ys => NS f ys -> g (NS f' ys)
go (Z x) = Z <$> f x
go (S xs) = S <$> go xs
traverse'_NS ::
forall xs f f' g. (SListI xs, Functor g)
=> (forall a. f a -> g (f' a)) -> NS f xs -> g (NS f' xs)
traverse'_NS f =
ctraverse'_NS topP f
{-# INLINE traverse'_NS #-}
ctraverse'_SOP :: (All2 c xss, Applicative g) => proxy c -> (forall a. c a => f a -> g (f' a)) -> SOP f xss -> g (SOP f' xss)
ctraverse'_SOP p f = fmap SOP . ctraverse'_NS (allP p) (ctraverse'_NP p f) . unSOP
traverse'_SOP :: (SListI2 xss, Applicative g) => (forall a. f a -> g (f' a)) -> SOP f xss -> g (SOP f' xss)
traverse'_SOP f =
ctraverse'_SOP topP f
{-# INLINE traverse'_SOP #-}
instance HSequence NS where
hsequence' = sequence'_NS
hctraverse' = ctraverse'_NS
htraverse' = traverse'_NS
instance HSequence SOP where
hsequence' = sequence'_SOP
hctraverse' = ctraverse'_SOP
htraverse' = traverse'_SOP
sequence_NS :: (SListI xs, Applicative f) => NS f xs -> f (NS I xs)
sequence_SOP :: (All SListI xss, Applicative f) => SOP f xss -> f (SOP I xss)
sequence_NS = hsequence
sequence_SOP = hsequence
ctraverse_NS :: (All c xs, Applicative g) => proxy c -> (forall a. c a => f a -> g a) -> NP f xs -> g (NP I xs)
ctraverse_SOP :: (All2 c xs, Applicative g) => proxy c -> (forall a. c a => f a -> g a) -> POP f xs -> g (POP I xs)
ctraverse_NS = hctraverse
ctraverse_SOP = hctraverse
cata_NS ::
forall r f xs .
(forall y ys . f y -> r (y ': ys))
-> (forall y ys . r ys -> r (y ': ys))
-> NS f xs
-> r xs
cata_NS z s = go
where
go :: forall ys . NS f ys -> r ys
go (Z x) = z x
go (S i) = s (go i)
ccata_NS ::
forall c proxy r f xs . (All c xs)
=> proxy c
-> (forall y ys . c y => f y -> r (y ': ys))
-> (forall y ys . c y => r ys -> r (y ': ys))
-> NS f xs
-> r xs
ccata_NS _ z s = go
where
go :: forall ys . (All c ys) => NS f ys -> r ys
go (Z x) = z x
go (S i) = s (go i)
ana_NS ::
forall s f xs . (SListI xs)
=> (forall r . s '[] -> r)
-> (forall y ys . s (y ': ys) -> Either (f y) (s ys))
-> s xs
-> NS f xs
ana_NS refute decide =
cana_NS topP refute decide
{-# INLINE ana_NS #-}
cana_NS :: forall c proxy s f xs .
(All c xs)
=> proxy c
-> (forall r . s '[] -> r)
-> (forall y ys . c y => s (y ': ys) -> Either (f y) (s ys))
-> s xs
-> NS f xs
cana_NS _ refute decide = go sList
where
go :: forall ys . (All c ys) => SList ys -> s ys -> NS f ys
go SNil s = refute s
go SCons s = case decide s of
Left x -> Z x
Right s' -> S (go sList s')
expand_NS :: forall f xs .
(SListI xs)
=> (forall x . f x)
-> NS f xs -> NP f xs
expand_NS d =
cexpand_NS topP d
{-# INLINE expand_NS #-}
cexpand_NS :: forall c proxy f xs .
(All c xs)
=> proxy c -> (forall x . c x => f x)
-> NS f xs -> NP f xs
cexpand_NS p d = go
where
go :: forall ys . All c ys => NS f ys -> NP f ys
go (Z x) = x :* hcpure p d
go (S i) = d :* go i
expand_SOP :: forall f xss .
(All SListI xss)
=> (forall x . f x)
-> SOP f xss -> POP f xss
expand_SOP d =
cexpand_SOP topP d
{-# INLINE cexpand_SOP #-}
cexpand_SOP :: forall c proxy f xss .
(All2 c xss)
=> proxy c -> (forall x . c x => f x)
-> SOP f xss -> POP f xss
cexpand_SOP p d =
POP . cexpand_NS (allP p) (hcpure p d) . unSOP
allP :: proxy c -> Proxy (All c)
allP _ = Proxy
instance HExpand NS where
hexpand = expand_NS
hcexpand = cexpand_NS
instance HExpand SOP where
hexpand = expand_SOP
hcexpand = cexpand_SOP
trans_NS ::
AllZip c xs ys
=> proxy c
-> (forall x y . c x y => f x -> g y)
-> NS f xs -> NS g ys
trans_NS _ t (Z x) = Z (t x)
trans_NS p t (S x) = S (trans_NS p t x)
trans_SOP ::
AllZip2 c xss yss
=> proxy c
-> (forall x y . c x y => f x -> g y)
-> SOP f xss -> SOP g yss
trans_SOP p t =
SOP . trans_NS (allZipP p) (trans_NP p t) . unSOP
allZipP :: proxy c -> Proxy (AllZip c)
allZipP _ = Proxy
coerce_NS ::
forall f g xs ys .
AllZip (LiftedCoercible f g) xs ys
=> NS f xs -> NS g ys
coerce_NS =
unsafeCoerce
_safe_coerce_NS ::
forall f g xs ys .
AllZip (LiftedCoercible f g) xs ys
=> NS f xs -> NS g ys
_safe_coerce_NS =
trans_NS (Proxy :: Proxy (LiftedCoercible f g)) coerce
coerce_SOP ::
forall f g xss yss .
AllZip2 (LiftedCoercible f g) xss yss
=> SOP f xss -> SOP g yss
coerce_SOP =
unsafeCoerce
_safe_coerce_SOP ::
forall f g xss yss .
AllZip2 (LiftedCoercible f g) xss yss
=> SOP f xss -> SOP g yss
_safe_coerce_SOP =
trans_SOP (Proxy :: Proxy (LiftedCoercible f g)) coerce
fromI_NS ::
forall f xs ys .
AllZip (LiftedCoercible I f) xs ys
=> NS I xs -> NS f ys
fromI_NS = hfromI
toI_NS ::
forall f xs ys .
AllZip (LiftedCoercible f I) xs ys
=> NS f xs -> NS I ys
toI_NS = htoI
fromI_SOP ::
forall f xss yss .
AllZip2 (LiftedCoercible I f) xss yss
=> SOP I xss -> SOP f yss
fromI_SOP = hfromI
toI_SOP ::
forall f xss yss .
AllZip2 (LiftedCoercible f I) xss yss
=> SOP f xss -> SOP I yss
toI_SOP = htoI
instance HTrans NS NS where
htrans = trans_NS
hcoerce = coerce_NS
instance HTrans SOP SOP where
htrans = trans_SOP
hcoerce = coerce_SOP