defun-sop-0.1: src/Data/SOP/NP/DeFun.hs
{-# LANGUAGE Trustworthy #-}
-- |
--
-- This module is designed to imported qualified:
--
-- @
-- import qualified Data.SOP.NP.DeFun as NP
-- @
--
module Data.SOP.NP.DeFun (
-- * Append
Append, AppendSym, AppendSym1,
append, appendSym, appendSym1,
-- * Map
Map, MapSym, MapSym1,
map, mapSym, mapSym1,
-- * Concat
Concat, ConcatSym,
concat, concatSym,
-- * ConcatMap
ConcatMap, ConcatMapSym, ConcatMapSym1,
concatMap, concatMapSym, concatMapSym1,
-- * Map2
Map2, Map2Sym, Map2Sym1, Map2Sym2,
map2, map2Sym, map2Sym1, map2Sym2,
-- * Sequence
Sequence, SequenceSym,
sequence, sequenceSym,
-- * Foldr
Foldr, FoldrSym, FoldrSym1, FoldrSym2,
foldr, foldrSym, foldrSym1, foldrSym2,
-- * Foldl
Foldl, FoldlSym, FoldlSym1, FoldlSym2,
foldl, foldlSym, foldlSym1, foldlSym2,
-- * ZipWith
ZipWith, ZipWithSym, ZipWithSym1, ZipWithSym2,
zipWith, zipWithSym, zipWithSym1, zipWithSym2,
-- * Reverse
Reverse, ReverseSym,
reverse, reverseSym,
) where
import DeFun.List
import Data.SOP.NP (NP (..))
import DeFun.Core
import DeFun.Function
-- $setup
-- >>> import Prelude (Char, Maybe (..), Show)
-- >>> import Numeric.Natural (Natural)
-- >>> import Data.SOP.NP (NP (..))
-- >>> import DeFun.Core
-- >>> :set -dppr-cols9999
--
-- >>> data Nat = Z | S Nat
-- >>> data SNat (n :: Nat) where { SZ :: SNat Z; SS :: SNat n -> SNat (S n) }
-- >>> deriving instance Show (SNat n)
-------------------------------------------------------------------------------
-- Append
-------------------------------------------------------------------------------
append :: NP a xs -> NP a ys -> NP a (Append xs ys)
append Nil ys = ys
append (x :* xs) ys = x :* append xs ys
appendSym :: Lam2 (NP a) (NP a) (NP a) AppendSym
appendSym = Lam appendSym1
appendSym1 :: NP a xs -> Lam (NP a) (NP a) (AppendSym1 xs)
appendSym1 xs = Lam (append xs)
-------------------------------------------------------------------------------
-- Map
-------------------------------------------------------------------------------
map :: Lam a b f -> NP a xs -> NP b (Map f xs)
map _ Nil = Nil
map f (x :* xs) = f @@ x :* map f xs
mapSym :: Lam (a :~> b) (Lam (NP a) (NP b)) MapSym
mapSym = Lam mapSym1
mapSym1 :: Lam a b f -> Lam (NP a) (NP b) (MapSym1 f)
mapSym1 f = Lam (map f)
-------------------------------------------------------------------------------
-- Concat
-------------------------------------------------------------------------------
concat :: NP (NP a) xss -> NP a (Concat xss)
concat Nil = Nil
concat (xs :* xss) = append xs (concat xss)
concatSym :: Lam (NP (NP a)) (NP a) ConcatSym
concatSym = Lam concat
-------------------------------------------------------------------------------
-- ConcatMap
-------------------------------------------------------------------------------
concatMap :: Lam a (NP b) f -> NP a xs -> NP b (ConcatMap f xs)
concatMap _ Nil = Nil
concatMap f (x :* xs) = append (f @@ x) (concatMap f xs)
concatMapSym :: Lam2 (a :~> NP b) (NP a) (NP b) ConcatMapSym
concatMapSym = Lam concatMapSym1
concatMapSym1 :: Lam a (NP b) f -> Lam (NP a) (NP b) (ConcatMapSym1 f)
concatMapSym1 f = Lam (concatMap f)
-------------------------------------------------------------------------------
-- Map2
-------------------------------------------------------------------------------
map2 :: Lam2 a b c f -> NP a xs -> NP b ys -> NP c (Map2 f xs ys)
map2 f xs ys = concatMap (compSym2 (flipSym2 mapSym ys) f) xs
map2Sym :: Lam3 (a :~> b :~> c) (NP a) (NP b) (NP c) Map2Sym
map2Sym = Lam map2Sym1
map2Sym1 :: Lam2 a b c f -> Lam2 (NP a) (NP b) (NP c) (Map2Sym1 f)
map2Sym1 f = Lam (map2Sym2 f)
map2Sym2 :: Lam2 a b c f -> NP a xs -> Lam (NP b) (NP c) (Map2Sym2 f xs)
map2Sym2 f xs = Lam (map2 f xs)
-------------------------------------------------------------------------------
-- Sequence
-------------------------------------------------------------------------------
sequence :: NP (NP a) xss -> NP (NP a) (Sequence xss)
sequence Nil = Nil :* Nil
sequence (xs :* xss) = map2 (con2 (:*)) xs (sequence xss)
sequenceSym :: Lam (NP (NP a)) (NP (NP a)) SequenceSym
sequenceSym = Lam sequence
-------------------------------------------------------------------------------
-- Foldr
-------------------------------------------------------------------------------
foldr :: Lam2 a b b f -> b x -> NP a ys -> b (Foldr f x ys)
foldr _ z Nil = z
foldr f z (x :* xs) = f @@ x @@ (foldr f z xs)
foldrSym :: Lam3 (a :~> b :~> b) b (NP a) b FoldrSym
foldrSym = Lam foldrSym1
foldrSym1 :: Lam2 a b b f -> Lam2 b (NP a) b (FoldrSym1 f)
foldrSym1 f = Lam (foldrSym2 f)
foldrSym2 :: Lam2 a b b f -> b x -> Lam (NP a) b (FoldrSym2 f x)
foldrSym2 f z = Lam (foldr f z)
-------------------------------------------------------------------------------
-- Foldl
-------------------------------------------------------------------------------
foldl :: Lam2 b a b f -> b x -> NP a ys -> b (Foldl f x ys)
foldl _ z Nil = z
foldl f z (x :* xs) = foldl f (f @@ z @@ x) xs
foldlSym :: Lam3 (b :~> a :~> b) b (NP a) b FoldlSym
foldlSym = Lam foldlSym1
foldlSym1 :: Lam2 b a b f -> Lam2 b (NP a) b (FoldlSym1 f)
foldlSym1 f = Lam (foldlSym2 f)
foldlSym2 :: Lam2 b a b f -> b x -> Lam (NP a) b (FoldlSym2 f x)
foldlSym2 f z = Lam (foldl f z)
-------------------------------------------------------------------------------
-- ZipWith
-------------------------------------------------------------------------------
zipWith :: Lam2 a b c f -> NP a xs -> NP b ys -> NP c (ZipWith f xs ys)
zipWith _ Nil _ = Nil
zipWith _ (_ :* _) Nil = Nil
zipWith f (x :* xs) (y :* ys) = f @@ x @@ y :* zipWith f xs ys
zipWithSym :: Lam3 (a :~> b :~> c) (NP a) (NP b) (NP c) ZipWithSym
zipWithSym = Lam zipWithSym1
zipWithSym1 :: Lam2 a b c f -> Lam2 (NP a) (NP b) (NP c) (ZipWithSym1 f)
zipWithSym1 f = Lam (zipWithSym2 f)
zipWithSym2 :: Lam2 a b c f -> NP a xs -> Lam (NP b) (NP c) (ZipWithSym2 f xs)
zipWithSym2 f xs = Lam (zipWith f xs)
-------------------------------------------------------------------------------
-- Reverse
-------------------------------------------------------------------------------
-- |
--
-- >>> reverse (SZ :* SS SZ :* SS (SS SZ) :* Nil)
-- SS (SS SZ) :* SS SZ :* SZ :* Nil
--
reverse :: NP a xs -> NP a (Reverse xs)
reverse = foldl (flipSym1 (con2 (:*))) Nil
reverseSym :: Lam (NP a) (NP a) ReverseSym
reverseSym = Lam reverse