defun-0.1: test/defun-tests.hs
module Main where
import Data.SOP (NP (..), NS (..))
import GHC.Generics ((:*:) (..))
import Prelude (IO, putStrLn, Either (..))
import qualified Prelude as P
import DeFun
main :: IO ()
main = putStrLn "OK"
-------------------------------------------------------------------------------
-- mapAppend
-------------------------------------------------------------------------------
mapAppend :: NP a xs -> NP (NP a) xss -> NP (NP a) (Map (AppendSym1 xs) xss)
mapAppend xs yss = map (appendSym @@ xs) yss
-------------------------------------------------------------------------------
-- split_NP
-------------------------------------------------------------------------------
-- | inverse of 'append'
split_NP :: NP pa xs -> NP a (Append xs ys) -> (NP a xs, NP a ys)
split_NP Nil xys = (Nil, xys)
split_NP (_ :* ps) (x :* xys) = let (xs, ys) = split_NP ps xys in (x :* xs, ys)
-------------------------------------------------------------------------------
-- FLATTEN utils
-------------------------------------------------------------------------------
map_NS :: Lam a b f -> NS a xs -> NS b (Map f xs)
map_NS f (Z x) = Z (f @@ x)
map_NS f (S xs) = S (map_NS f xs)
map_NS' :: Lam (px :*: a) b f -> NP px xs -> NS a xs -> NS b (Map f xs)
map_NS' _ Nil x = case x of {}
map_NS' f (px :* _) (Z x) = Z (f @@ (px :*: x))
map_NS' f (_ :* pxs) (S xs) = S (map_NS' f pxs xs)
append_NS :: forall xs ys f sing. NP sing xs -> Either (NS f xs) (NS f ys) -> NS f (Append xs ys)
append_NS _ (Left xs) = goLeft xs where
goLeft :: NS f xs' -> NS f (Append xs' ys)
goLeft (Z x) = Z x
goLeft (S x) = S (goLeft x)
append_NS xs (Right ys0) = goRight xs ys0 where
goRight :: NP sing xs' -> NS f ys -> NS f (Append xs' ys)
goRight Nil ys = ys
goRight (_ :* xs') ys = S (goRight xs' ys)
concatMap_NS :: Lam pa (NP pb) f -> NP pa xs -> Lam a (NS b) f -> NS a xs -> NS b (ConcatMap f xs)
concatMap_NS pf pxs f = concatMap_NS' pf pxs (Lam (\(_ :*: x) -> f @@ x))
concatMap_NS' :: Lam pa (NP pb) f -> NP pa xs -> Lam (pa :*: a) (NS b) f -> NS a xs -> NS b (ConcatMap f xs)
concatMap_NS' _ Nil = \_ xs -> case xs of {}
concatMap_NS' pf (px :* pxs) = concatMap_NS_aux' pf px pxs
concatMap_NS_aux' :: forall a b f x xs pa pb. Lam pa (NP pb) f -> pa x -> NP pa xs -> Lam (pa :*: a) (NS b) f -> NS a (x : xs) -> NS b (ConcatMap f (x : xs))
concatMap_NS_aux' pf px _pxs f (Z x) = append_NS
@_
@(ConcatMap f xs)
(pf @@ px)
(Left (f @@ (px :*: x)))
concatMap_NS_aux' pf px pxs f (S xs) = append_NS
@_
@(ConcatMap f xs)
(pf @@ px)
(Right (concatMap_NS' pf pxs f xs))
map2_NS :: forall a b c f xs ys pa pb pc.
Lam2 pa pb pc f -> NP pa xs -> NP pb ys ->
Lam2 a b c f -> NS a xs -> NS b ys -> NS c (Map2 f xs ys)
map2_NS pf pxs pys f xs ys = concatMap_NS
(compSym2 (flipSym2 mapSym pys) pf)
pxs
(compSym2 (flipSym2 (mkLam2 map_NS) ys) f)
xs
sequence_NSNP :: NP (NP sing) xss -> NP (NS f) xss -> NS (NP f) (Sequence xss)
sequence_NSNP Nil Nil = Z Nil
sequence_NSNP (xs :* xss) (ys :* yss) = map2_NS
(con2 (:*))
xs
(sequence xss)
(con2 (:*))
ys
(sequence_NSNP xss yss)
sequence_NSNP_sym :: Lam (NP (NP sing) :*: NP (NS f)) (NS (NP f)) SequenceSym
sequence_NSNP_sym = Lam (\(pxss :*: xss) -> sequence_NSNP pxss xss)
-------------------------------------------------------------------------------
-- FLATTEN
-------------------------------------------------------------------------------
-- given as sum-of-products of sum-of-products,
-- we can turn it into big sum-of-products.
flattenList :: [[[[k]]]] -> [[k]]
flattenList = P.concatMap (P.map P.concat P.. P.sequence)
type FLATTEN xsss = ConcatMap (CompSym2 (MapSym1 ConcatSym) SequenceSym) xsss
-- This is an isomorphism.
flatten_NSNP :: forall xssss f sing. NP (NP (NP (NP sing))) xssss -> NS (NP (NS (NP f))) xssss -> NS (NP f) (FLATTEN xssss)
flatten_NSNP pxssss xssss = concatMap_NS'
(compSym2 (mapSym1 concatSym) sequenceSym)
pxssss
(compSym2 (Lam (map_NS concatSym)) sequence_NSNP_sym)
xssss