{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
module Generics.MRSOP.Base.NP
( SOP.NP(..)
, appendNP
, listPrfNP
, mapNP
, mapNPM
, elimNP
, elimNPM
, zipNP
, unzipNP
, cataNP
, cataNPM
, eqNP
) where
import Data.SOP.NP (NP(..))
import qualified Data.SOP.NP as SOP
import Generics.MRSOP.Util
appendNP :: NP p xs -> NP p ys -> NP p (xs :++: ys)
appendNP Nil ays = ays
appendNP (a :* axs) ays = a :* appendNP axs ays
listPrfNP :: NP p xs -> ListPrf xs
listPrfNP Nil = LP_Nil
listPrfNP (_ :* xs) = LP_Cons $ listPrfNP xs
mapNP :: f :-> g -> NP f ks -> NP g ks
mapNP _ Nil = Nil
mapNP f (k :* ks) = f k :* mapNP f ks
mapNPM :: (Monad m) => (forall x . f x -> m (g x)) -> NP f ks -> m (NP g ks)
mapNPM _ Nil = return Nil
mapNPM f (k :* ks) = (:*) <$> f k <*> mapNPM f ks
elimNP :: (forall x . f x -> a) -> NP f ks -> [a]
elimNP _ Nil = []
elimNP f (k :* ks) = f k : elimNP f ks
elimNPM :: (Monad m) => (forall x . f x -> m a) -> NP f ks -> m [a]
elimNPM _ Nil = return []
elimNPM f (k :* ks) = (:) <$> f k <*> elimNPM f ks
zipNP :: NP f xs -> NP g xs -> NP (f :*: g) xs
zipNP Nil Nil = Nil
zipNP (f :* fs) (g :* gs) = (f :*: g) :* zipNP fs gs
unzipNP :: NP (f :*: g) xs -> (NP f xs , NP g xs)
unzipNP Nil = (Nil , Nil)
unzipNP (Pair f g :* fgs) = (f :*) *** (g :*) $ unzipNP fgs
cataNP :: (forall a as . f a -> r as -> r (a : as))
-> r '[]
-> NP f xs -> r xs
cataNP _fCons fNil Nil = fNil
cataNP fCons fNil (k :* ks) = fCons k (cataNP fCons fNil ks)
cataNPM :: (Monad m)
=> (forall a as . f a -> r as -> m (r (a : as)))
-> m (r '[])
-> NP f xs -> m (r xs)
cataNPM _fCons fNil Nil = fNil
cataNPM fCons fNil (k :* ks) = cataNPM fCons fNil ks >>= fCons k
eqNP :: (forall x. p x -> p x -> Bool)
-> NP p xs -> NP p xs -> Bool
eqNP p x = and . elimNP (uncurry' p) . zipNP x