pointless-rewrite-0.0.3: src/Transform/Rules/Lenses/Dists.hs
-----------------------------------------------------------------------------
-- |
-- Module : Transform.Rules.Lenses.Dists
-- 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 distribution of products over sums and vice-versa.
--
-----------------------------------------------------------------------------
module Transform.Rules.Lenses.Dists where
import Data.Type
import Data.Pf
import Data.Lens
import Transform.Rewriting
import Transform.Rules.Lenses.Combinators
import {-# SOURCE #-} qualified Transform.Rules.PF as PF
import Prelude hiding (Functor(..))
import Control.Monad hiding (Functor(..))
-- ** Distr
distr_def_lns :: Rule
distr_def_lns (Lns (Prod c (Either a b)) _) DISTR_LNS = do
let t = Either (Prod a c) (Prod b c)
t' = Prod (Either a b) c
success "distr-Def-Lns" $ COMP_LNS t (SWAP_LNS -|-<< SWAP_LNS) $ COMP_LNS t' DISTL_LNS SWAP_LNS
distr_def_lns _ _ = mzero
undistr_def_lns :: Rule
undistr_def_lns (Lns _ (Prod c (Either a b))) UNDISTR_LNS = do
let t = Prod (Either a b) c
t' = Either (Prod a c) (Prod b c)
success "undistr-Def-Lns" $ COMP_LNS t SWAP_LNS $ COMP_LNS t' UNDISTL_LNS $ (SWAP_LNS -|-<< SWAP_LNS)
undistr_def_lns _ _ = mzero
-- ** Distl
distl_iso_lns = comp_lns distl_iso_lns'
distl_iso_lns' :: Rule
distl_iso_lns' _ (COMP_LNS _ DISTL_LNS UNDISTL_LNS) =
success "distl-Iso-Lns" ID_LNS
distl_iso_lns' _ _ = mzero
undistl_iso_lns = comp_lns undistl_iso_lns'
undistl_iso_lns' :: Rule
undistl_iso_lns' _ (COMP_LNS _ UNDISTL_LNS DISTL_LNS) =
success "undistl-Iso-Lns" ID_LNS
undistl_iso_lns' _ _ = mzero
distl_fst_cancel_lns = comp_lns distl_fst_cancel_lns'
distl_fst_cancel_lns' :: Rule
distl_fst_cancel_lns' (Lns (Prod _ c) _) (COMP_LNS _ (SUMW_LNS (ID `PROD` SND) (ID `PROD` SND) (FST_LNS f) (FST_LNS g)) DISTL_LNS) =
success "distl-Fst-Cancel-Lns" $ FST_LNS (f \/= g)
distl_fst_cancel_lns' _ _ = mzero
distl_snd_cancel_lns = comp_lns distl_snd_cancel_lns'
distl_snd_cancel_lns' :: Rule
distl_snd_cancel_lns' q@(Lns (Prod (Either a b) c) _) v@(COMP_LNS _ (EITHER_LNS p (SND_LNS f) (SND_LNS g)) DISTL_LNS) = do
debug "distl-Snd-Cancel-Lns" (Pf q) v
let h = COMP (Either c c) (f -|-= g) $ (?=) c p
h' <- PF.optimise_pf (Fun c (Either a b)) h
success "distl-Snd-Cancel-Lns" $ SND_LNS h'
distl_snd_cancel_lns' _ _ = mzero
distl_id_cancel_lns = comp_lns distl_id_cancel_lns'
distl_id_cancel_lns' :: Rule
distl_id_cancel_lns' (Lns _ _) (COMP_LNS _ (EITHER_LNS (COMP _ p FST) ID_LNS ID_LNS) DISTL_LNS) = do
success "distl-Id-Cancel-Lns" $ (EITHER_LNS p ID_LNS ID_LNS) ><<< ID_LNS
distl_id_cancel_lns' _ _ = mzero
distl_fusion_lns = comp_lns distl_fusion_lns'
distl_fusion_lns' :: Rule
distl_fusion_lns' (Lns _ _) (COMP_LNS _ DISTL_LNS (f `PROD_LNS` ID_LNS)) = mzero
distl_fusion_lns' q@(Lns (Prod a c) _) v@(COMP_LNS (Prod (Either a' b') c') DISTL_LNS (l1 `PROD_LNS` l3)) = (do
let (t,t') = (Either (Prod a' c) (Prod b' c),Prod (Either a' b') c)
inv (Lns c c') l3
debug "distl-Fusion-Lns" (Pf q) v
success "distl-Fusion-Lns" $ COMP_LNS t (ID_LNS ><<< l3 -|-<< ID_LNS ><<< l3) $ COMP_LNS t' DISTL_LNS $ (l1 ><<< ID_LNS))
`mplus` (do
debug "distl-Fusion-Lns" (Pf q) v
let (t,t') = (Either (Prod a' c) (Prod b' c),Prod (Either a' b') c)
h = COMP (Prod (Prod a' b') (Prod c' c)) (FST ><= putof (Lns c c') l3) distp_pf
i = COMP (Prod (Prod b' a') (Prod c' c)) (FST ><= putof (Lns c c') l3) distp_pf
debug "distlFusionH" (Pf $ (Fun (Prod (Prod a' c') (Prod b' c)) (Prod a' c))) h
h' <- PF.optimise_pf (Fun (Prod (Prod a' c') (Prod b' c)) (Prod a' c)) h
i' <- PF.optimise_pf (Fun (Prod (Prod b' c') (Prod a' c)) (Prod b' c)) i
success "distl-Fusion-Lns" $ COMP_LNS t (SUMW_LNS h' i' (ID_LNS ><<< l3) (ID_LNS ><<< l3)) $ COMP_LNS t' DISTL_LNS $ l1 ><<< ID_LNS
)
distl_fusion_lns' _ _ = mzero
distl_nat_lns = postcomp_lns leftmost_prod_lns distl_nat_lns'
distl_nat_lns' :: Rule
distl_nat_lns' (Lns _ _) (COMP_LNS _ DISTL_LNS (ID_LNS `PROD_LNS` ID_LNS)) = mzero
--distl_nat_lns' (Lns a c) (COMP_LNS b DISTL_LNS (ID_LNS `PROD_LNS` f)) =
-- distl_nat_lns' (Lns a c) (COMP_LNS b DISTL_LNS ((ID_LNS `SUM_LNS` ID_LNS) `PROD_LNS` f))
distl_nat_lns' q@(Lns (Prod (Either a b) c) _) v@(COMP_LNS (Prod (Either a' b') c') DISTL_LNS ((SUM_LNS l1 l2) `PROD_LNS` l3)) = (do
debug "distl-Nat-Lns" (Pf q) v
inv (Lns c c') l3
success "distl-Nat-Lns" $ COMP_LNS (Either (Prod a c) (Prod b c)) ((l1 ><<< l3) -|-<< (l2 ><<< l3)) DISTL_LNS)
`mplus` (do
debug "distl-Nat-Lns" (Pf q) v
let h = COMP (Prod (Prod a' b) (Prod c' c)) (COMP a' (createof (Lns a a') l1) FST ><= (putof (Lns c c') l3)) distp_pf
i = COMP (Prod (Prod b' a) (Prod c' c)) (COMP b' (createof (Lns b b') l2) FST ><= (putof (Lns c c') l3)) distp_pf
h' <- PF.optimise_pf (Fun (Prod (Prod a' c') (Prod b c)) (Prod a c)) h
i' <- PF.optimise_pf (Fun (Prod (Prod b' c') (Prod a c)) (Prod b c)) i
success "distl-Nat-Lns" $ COMP_LNS (Either (Prod a c) (Prod b c)) (SUMW_LNS h' i' (l1 ><<< l3) (l2 ><<< l3)) DISTL_LNS)
distl_nat_lns' q@(Lns (Prod (Either a b) c) _) v@(COMP_LNS (Prod (Either a' b') c') DISTL_LNS ((SUMW_LNS f g l1 l2) `PROD_LNS` l3)) = do
debug "distl-Nat-Lns" (Pf q) v
let h = COMP (Prod (Prod a' b) (Prod c' c)) (f ><= (putof (Lns c c') l3)) distp_pf
i = COMP (Prod (Prod b' a) (Prod c' c)) (g ><= (putof (Lns c c') l3)) distp_pf
h' <- PF.optimise_pf (Fun (Prod (Prod a' c') (Prod b c)) (Prod a c)) h
i' <- PF.optimise_pf (Fun (Prod (Prod b' c') (Prod a c)) (Prod b c)) i
success "distl-Nat-Lns" $ COMP_LNS (Either (Prod a c) (Prod b c)) (SUMW_LNS h' i' (l1 ><<< l3) (l2 ><<< l3)) DISTL_LNS
distl_nat_lns' _ _ = mzero
distl_sum_nat_lns = comp_lns distl_sum_nat_lns'
distl_sum_nat_lns' :: Rule
distl_sum_nat_lns' (Lns (Prod (Either a b) c) _) (COMP_LNS (Prod (Either d e) f) DISTL_LNS ((EITHER_LNS p l1 l2) `PROD_LNS` l3)) = do
let (t,t') = (Prod (Either d e) f,Either (Prod a c) (Prod b c))
p' = COMP (Either d e) p FST
success "distl-Sum-Nat-Lns" $ COMP_LNS t DISTL_LNS $ COMP_LNS t' (EITHER_LNS p' (l1 ><<< l3) (l2 ><<< l3)) DISTL_LNS
distl_sum_nat_lns' _ _ = mzero
dists :: Rule
dists = top distr_def_lns ||| top undistr_def_lns
||| top distl_iso_lns ||| top undistl_iso_lns
||| top distl_fst_cancel_lns ||| top distl_snd_cancel_lns ||| top distl_id_cancel_lns