packages feed

pointless-rewrite-0.0.3: src/Transform/Rules/Lenses/Lists.hs

-----------------------------------------------------------------------------
-- |
-- Module      :  Transform.Rules.Lenses.Lists
-- Copyright   :  (c) 2010 University of Minho
-- License     :  BSD3
--
-- Maintainer  :  hpacheco@di.uminho.pt
-- Stability   :  experimental
-- Portability :  non-portable
--
-- Pointless Rewrite:
-- automatic transformation system for point-free programs
-- 
-- Combinators for the rewriting of point-free lenses involving lists.
--
-----------------------------------------------------------------------------

module Transform.Rules.Lenses.Lists where

import Data.Type
import Data.Pf
import Data.Eval
import Data.Lens
import Transform.Rewriting
import Transform.Rules.Lenses.Combinators

import Prelude hiding (Functor(..))
import Control.Monad hiding (Functor(..))

import Generics.Pointless.Functors
import Generics.Pointless.Lenses

-- ** List laws

map_id_lns :: Rule
map_id_lns (Lns _ _) (MAP_LNS ID_LNS) =
    success "map-Id-Lns" $ ID_LNS
map_id_lns _ _ = mzero

map_fusion_lns = comp_lns map_fusion_lns'
map_fusion_lns' :: Rule
map_fusion_lns' (Lns _ _) (COMP_LNS (List c) (MAP_LNS l1) (MAP_LNS l2)) =
    success "map-Fusion-Lns" $ MAP_LNS $ COMP_LNS c l1 l2
map_fusion_lns' _ _ = mzero

leftmost_map_lns :: Rule
leftmost_map_lns (Lns (List a) (List b)) (MAP_LNS l1) = do
    (COMP_LNS c f g) <- leftmost_lns' (Lns a b) l1
    return $ COMP_LNS (List c) (MAP_LNS f) (MAP_LNS g)
leftmost_map_lns _ _ = mzero

map_cat_lns = comp_lns map_cat_lns'
map_cat_lns' :: Rule
map_cat_lns' (Lns _ lb) (COMP_LNS _ (MAP_LNS l1) CAT_LNS) =
    success "map-Cat-Lns" $ COMP_LNS (Prod lb lb) CAT_LNS (MAP_LNS l1 ><<< MAP_LNS l1)
map_cat_lns' _ _ = mzero

map_concat_lns = comp_lns map_concat_lns'
map_concat_lns' :: Rule
map_concat_lns' (Lns _ lb) (COMP_LNS _ (MAP_LNS l1) CONCAT_LNS) =
    success "map-Concat-Lns" $ COMP_LNS (List lb) CONCAT_LNS $ MAP_LNS $ MAP_LNS l1
map_concat_lns' _ _ = mzero

filter_cat_lns = comp_lns filter_cat_lns'
filter_cat_lns' :: Rule
filter_cat_lns' (Lns _ la) (COMP_LNS _ FILTER_LEFT_LNS CAT_LNS) =
    success "filter-Cat-Lns" $ COMP_LNS (Prod la la) CAT_LNS (FILTER_LEFT_LNS ><<< FILTER_LEFT_LNS)
filter_cat_lns' (Lns _ lb) (COMP_LNS _ FILTER_RIGHT_LNS CAT_LNS) =
    success "filter-Cat-Lns" $ COMP_LNS (Prod lb lb) CAT_LNS (FILTER_RIGHT_LNS ><<< FILTER_RIGHT_LNS)
filter_cat_lns' _ _ = mzero

filter_map_lns = postcomp_lns leftmost_map_lns filter_map_lns'
filter_map_lns' :: Rule
filter_map_lns' (Lns (List (Either a b)) _) (COMP_LNS _ FILTER_LEFT_LNS (MAP_LNS (l1 `SUM_LNS` l2))) = do
    success "filter-Map-Lns" $ COMP_LNS (List a) (MAP_LNS l1) FILTER_LEFT_LNS
filter_map_lns' (Lns (List (Either a b)) _) (COMP_LNS _ FILTER_LEFT_LNS (MAP_LNS (SUMW_LNS _ _ l1 l2))) = do
    success "filter-Map-Lns" $ COMP_LNS (List a) (MAP_LNS l1) FILTER_LEFT_LNS
filter_map_lns' (Lns (List (Either a b)) _) (COMP_LNS _ FILTER_RIGHT_LNS (MAP_LNS (l1 `SUM_LNS` l2))) = do
    success "filter-Map-Lns" $ COMP_LNS (List b) (MAP_LNS l2) FILTER_RIGHT_LNS
filter_map_lns' (Lns (List (Either a b)) _) (COMP_LNS _ FILTER_RIGHT_LNS (MAP_LNS (SUMW_LNS _ _ l1 l2))) = do
    success "filter-Map-Lns" $ COMP_LNS (List b) (MAP_LNS l2) FILTER_RIGHT_LNS
filter_map_lns' _ _ = mzero

filter_concat_lns = comp_lns filter_concat_lns'
filter_concat_lns' :: Rule
filter_concat_lns' (Lns _ la) (COMP_LNS _ FILTER_LEFT_LNS CONCAT_LNS) =
    success "filter-Concat-Lns" $ COMP_LNS (List la) CONCAT_LNS $ MAP_LNS FILTER_LEFT_LNS
filter_concat_lns' (Lns _ lb) (COMP_LNS _ FILTER_RIGHT_LNS CONCAT_LNS) =
    success "filter-Concat-Lns" $ COMP_LNS (List lb) CONCAT_LNS $ MAP_LNS FILTER_RIGHT_LNS
filter_concat_lns' _ _ = mzero

sum_cat_lns = comp_lns sum_cat_lns'
sum_cat_lns' :: Rule
sum_cat_lns' (Lns _ _) (COMP_LNS _ SUMN_LNS CAT_LNS) =
    success "sum-Cat-Lns" $ COMP_LNS (Prod nat nat) PLUSN_LNS (SUMN_LNS ><<< SUMN_LNS)
sum_cat_lns' _ _ = mzero

sum_concat_lns = comp_lns sum_concat_lns'
sum_concat_lns' :: Rule
sum_concat_lns' (Lns _ _) (COMP_LNS _ SUMN_LNS CONCAT_LNS) =
    success "sum-Concat-Lns" $ COMP_LNS (List nat) SUMN_LNS (MAP_LNS SUMN_LNS)
sum_concat_lns' _ _ = mzero

length_cat_lns = comp_lns length_cat_lns'
length_cat_lns' :: Rule
length_cat_lns' (Lns _ _) (COMP_LNS _ (LENGTH_LNS f) CAT_LNS) =
    success "length-Cat-Lns" $ COMP_LNS (Prod nat nat) PLUSN_LNS $ LENGTH_LNS f ><<< LENGTH_LNS f
length_cat_lns' _ _ = mzero

length_map_lns = comp_lns length_map_lns'
length_map_lns' :: Rule
length_map_lns' t@(Lns la@(List a) _) v@(COMP_LNS lb@(List b) (LENGTH_LNS va) (MAP_LNS l1)) = do
    debug "length-Map-Lns" (Pf t) v
    let va' = (eval (Fun b a) (createof (Lns a b) l1)) va
    success "length-Map-Lns" $ LENGTH_LNS va'
length_map_lns' _ _ = mzero

length_concat_lns = comp_lns length_concat_lns'
length_concat_lns' :: Rule
length_concat_lns' (Lns _ _) (COMP_LNS _ (LENGTH_LNS f) CONCAT_LNS) =
    success "length-Concat-Lns" $ COMP_LNS (List nat) SUMN_LNS $ MAP_LNS $ LENGTH_LNS f
length_concat_lns' _ _ = mzero

cata_map_fusion_lns = comp_lns cata_map_fusion_lns'
cata_map_fusion_lns' :: Rule
cata_map_fusion_lns' (Lns la c) (COMP_LNS lb@(List b) (CATA_LNS l1) (MAP_LNS l2)) =
    success "cata-Map-Fusion-Lns" $ CATA_LNS $ COMP_LNS (Either One (Prod b c)) l1 $ ID_LNS -|-<< l2 ><<< ID_LNS
cata_map_fusion_lns' _ _ = mzero

ana_map_fusion_lns = comp_lns ana_map_fusion_lns'
ana_map_fusion_lns' :: Rule
ana_map_fusion_lns' (Lns a lc) (COMP_LNS lb@(List b) (MAP_LNS l2) (ANA_LNS l1)) =
    success "ana-Map-Fusion-Lns" $ ANA_LNS $ COMP_LNS (Either One (Prod b a)) (ID_LNS -|-<< l2 ><<< ID_LNS) l1
ana_map_fusion_lns' _ _ = mzero

-- ** Definitions

list_defs_lns :: Rule
list_defs_lns = list_catas_defs_lns ||| list_anas_defs_lns ||| list_hylos_defs_lns

list_catas_defs_lns :: Rule
list_catas_defs_lns = top map_cata_def_lns ||| top length_cata_def_lns
         ||| top concat_def_lns ||| top sum_def_lns ||| top filter_def_lns

list_anas_defs_lns :: Rule
list_anas_defs_lns = top map_ana_def_lns ||| top length_ana_def_lns

list_hylos_defs_lns :: Rule
list_hylos_defs_lns = top plus_def_lns ||| top cat_def_lns

inle :: Type a -> Type b -> Pf (Lens (Either a (Either a b)) (Either a b))
inle a b = COMP_LNS (Either (Either a a) b) ((EITHER_LNS (COMP One INL BANG) ID_LNS ID_LNS) -|-<< ID_LNS) COASSOCL_LNS

inre :: Type a -> Type b -> Pf (Lens (Either (Either a b) b) (Either a b))
inre a b = COMP_LNS (Either a (Either b b)) (ID_LNS -|-<< (EITHER_LNS (COMP One INR BANG) ID_LNS ID_LNS)) COASSOCR_LNS

map_cata_def_lns :: Rule
map_cata_def_lns (Lns _ lb@(List b)) (MAP_LNS l1) =
    success "map-Cata-Def-Lns" $ CATA_LNS $ COMP_LNS (Either One (Prod b lb)) INN_LNS (ID_LNS -|-<< l1 ><<< ID_LNS)
map_cata_def_lns _ _ = mzero

map_ana_def_lns :: Rule
map_ana_def_lns (Lns la@(List a) _) (MAP_LNS l1) =
    success "map-Ana-Def-Lns" $ ANA_LNS $ COMP_LNS (Either One (Prod a la)) (ID_LNS -|-<< l1 ><<< ID_LNS) OUT_LNS
map_ana_def_lns _ _ = mzero

filter_def_lns :: Rule
filter_def_lns (Lns (List (Either a b)) la) FILTER_LEFT_LNS = do
    let e = (\/<<) (COMP One INL BANG) INN_LNS (SND_LNS TOP)
        t = Either (Either One (Prod a la)) (Prod b la)
        t' = Either One (Either (Prod a la) (Prod b la))
    success "filter-Def-Lns" $ CATA_LNS $ COMP_LNS t e $ COMP_LNS t' COASSOCL_LNS (ID_LNS -|-<< DISTL_LNS)
filter_def_lns (Lns (List (Either a b)) lb) FILTER_RIGHT_LNS = do
    let e = (\/<<) (COMP One INL BANG) INN_LNS (SND_LNS TOP)
        t = Either (Either One (Prod b lb)) (Prod a lb)
        t' = Either One (Either (Prod b lb) (Prod a lb))
        t'' = Either (Prod a lb) (Prod b lb)
    success "filter-Def-Lns" $ CATA_LNS $ COMP_LNS t e $ COMP_LNS t' COASSOCL_LNS (ID_LNS -|-<< COMP_LNS t'' COSWAP_LNS DISTL_LNS)
filter_def_lns _ _ = mzero

length_cata_def_lns :: Rule
length_cata_def_lns (Lns _ _) (LENGTH_LNS v) = do
    let f = COMP One (PNT v) BANG
    success "length-Cata-Def-Lns" $ CATA_LNS $ COMP_LNS (Either One nat) INN_LNS (ID_LNS -|-<< SND_LNS f)
length_cata_def_lns _ _ = mzero

length_ana_def_lns :: Rule
length_ana_def_lns (Lns la@(List a) _) (LENGTH_LNS v) = do
    let f = COMP One (PNT v) BANG
    success "length-Ana-Def-Lns" $ ANA_LNS $ COMP_LNS (Either One (Prod a la)) (ID_LNS -|-<< SND_LNS f) OUT_LNS
length_ana_def_lns _ _ = mzero

cat_def_lns :: Rule
cat_def_lns (Lns _ la@(List a)) CAT_LNS = do
    let t = Prod (Either One (Prod a la)) la
        t' = Either (Prod One la) (Prod (Prod a la) la)
        t'' = Either (Either One (Prod a la)) (Prod a la)
        t''' = Either One (Prod a la)
        g = CATA_LNS $ COMP_LNS t''' INN_LNS $ COMP_LNS t'' (inre One (Prod a la)) (OUT_LNS -|-<< ID_LNS)
        h = ANA_LNS $ COMP_LNS t' (SND_LNS BANG -|-<< ASSOCR_LNS) $ COMP_LNS t DISTL_LNS (OUT_LNS ><<< ID_LNS)
        f = fixof (K la :+!: (K a :*!: I))
    success "cat-Def-Lns" $ COMP_LNS f g h
cat_def_lns _ _ = mzero

concat_def_lns :: Rule
concat_def_lns (Lns _ la@(List a)) CONCAT_LNS = do
    let aux = COMP_LNS (Either One (Either One (Prod a la))) (inle One (Prod a la)) (ID_LNS -|-<< (COMP_LNS la OUT_LNS CAT_LNS))
    success "concat-Def-Lns" $ CATA_LNS $ COMP_LNS (Either One (Prod a la)) INN_LNS aux
concat_def_lns _ _ = mzero

plus_def_lns :: Rule
plus_def_lns (Lns _ _) PLUSN_LNS = do
    let t = Prod (Either One nat) nat
        t' = Either (Prod One nat) (Prod nat nat)
        t'' = Either (Either One nat) nat
        l1 = COMP_LNS (Either One nat) INN_LNS $ COMP_LNS t'' (inre One nat) (OUT_LNS -|-<< ID_LNS)
        l2 = COMP_LNS t' (SND_LNS BANG -|-<< ID_LNS) $ COMP_LNS t DISTL_LNS (OUT_LNS ><<< ID_LNS)
        f = typeof :: Type (Fix (Const Nat :+: Id))
    success "plus-Def-Lns" $ COMP_LNS f (CATA_LNS l1) (ANA_LNS l2)
plus_def_lns _ _ = mzero

sum_def_lns :: Rule
sum_def_lns (Lns _ _) SUMN_LNS = do
    let t = Either One (Either One nat)
        aux = COMP_LNS t (inle One nat) (ID_LNS -|-<< (COMP_LNS nat OUT_LNS PLUSN_LNS))
    success "sum-Def-Lns" $ CATA_LNS $ COMP_LNS (Either One nat) INN_LNS aux
sum_def_lns _ _ = mzero

lists :: Rule
lists = top map_id_lns ||| top map_fusion_lns
    ||| top map_cat_lns ||| top map_concat_lns
    ||| top filter_cat_lns ||| top filter_map_lns ||| top filter_concat_lns
    ||| top sum_cat_lns ||| top sum_concat_lns
    ||| top length_cat_lns ||| top length_map_lns ||| top length_concat_lns