packages feed

pointless-rewrite-0.0.1: src/Transform/Rules/Lenses.hs

-----------------------------------------------------------------------------
-- |
-- Module      :  Transform.Rules.Lenses
-- 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
-- 
-- Generic strategy for the rewriting of point-free lenses.
--
-----------------------------------------------------------------------------

module Transform.Rules.Lenses where

import Data.Type
import Data.Equal
import Data.Lens
import Transform.Rewriting
import Transform.Rules.Lenses.Combinators
import Transform.Rules.Lenses.Products
import Transform.Rules.Lenses.Sums
import Transform.Rules.Lenses.Dists
import Transform.Rules.Lenses.Rec
import Transform.Rules.Lenses.Lists
import {-# SOURCE #-} qualified Transform.Rules.PF as PF

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

import Generics.Pointless.Lenses

-- * Strategies

optimise_lns :: Rule
optimise_lns = step1
    where
    step1 = outermost (top comp_assocr_lns ||| rules) >>> right >>> try (once fuse >>> optimise_lns)
    right = many (once (top comp_assocr_lns))
    rules = top nat_id_lns ||| prot ||| undef ||| prods ||| sums ||| bangs ||| dists ||| convs ||| lists ||| recs
    prot  = top unprotect_lns
    undef = top top_fusion_lns
    prods = top prod_functor_id_lns ||| top prod_functor_comp_lns
        ||| top fst_nat_lns ||| top snd_nat_lns
        ||| top swap_nat_lns ||| top swap_iso_lns ||| top swap_cancel_lns
        ||| top assocr_nat_lns ||| top assocr_iso_lns ||| top assocr_fst_cancel_lns ||| top assocr_snd_cancel_lns
        ||| top assocl_nat_lns ||| top assocl_iso_lns ||| top assocl_fst_cancel_lns ||| top assocl_snd_cancel_lns
        ||| top bangl_cancel_lns ||| top bangr_cancel_lns
    sums  = top sum_functor_id_lns ||| top sum_functor_comp_lns ||| top sum_absor_lns
        ||| top sumw_functor_id_lns ||| top sumw_absor_lns
        ||| top coswap_nat_lns ||| top coswap_iso_lns ||| top coswap_cancel_lns
        ||| top coassocr_nat_lns ||| top coassocr_iso_lns ||| top coassocl_nat_lns ||| top coassocl_iso_lns
    bangs = top bang_reflex_lns ||| top bang_fusion_lns ||| top bang_uniq_lns
    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
    convs = top rconv_cancel_lns ||| top lconv_cancel_lns ||| top conv_conv_lns ||| top conv_iso_lns
        ||| top conv_comp_lns ||| top conv_prod_lns ||| top conv_sum_lns
    recs  = top in_iso_lns ||| top out_iso_lns
        ||| top functor_id_lns ||| top functor_comp_lns ||| top functor_def_lns
        ||| top cata_reflex_lns ||| top cata_cancel_lns
        ||| top ana_reflex_lns ||| top ana_cancel_lns
    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
        ||| top cata_map_fusion_lns ||| top ana_map_fusion_lns
    fuse  = top sum_fusion_lns ||| top distl_fusion_lns ||| top distl_nat_lns ||| top distl_sum_nat_lns
        ||| top hylo_id_lns ||| top cata_fusion_lns ||| top ana_fusion_lns
        ||| top hylo_shift_lns
        ||| {-top sumw_def_lns ||| -}top sumw_functor_comp_lns

-- * Proofs

proveLns :: Type (Lens c a) -> Pf (Lens c a) -> IO ()
proveLns t@(Lns c a) l = do
    putStr "Proving CreateGet"
    eq1 <- reduceIO PF.optimise_pf (Fun a a) (COMP c (getof t l) (createof t l))
    print $ geq (Pf $ Fun a a) eq1 ID
    putStr "Proving PutGet"
    eq2 <- reduceIO PF.optimise_pf (Fun (Prod a c) a) (COMP c (getof t l) (putof t l))
    print $ geq (Pf $ Fun (Prod a c) a) eq2 FST
    putStr "Proving GetPut"
    eq3 <- reduceIO PF.optimise_pf (Fun c c) (COMP (Prod a c) (putof t l) ((getof t l) /\= ID))
    print $ geq (Pf $ Fun c c) eq3 ID

proveLnsRule :: Type (Lens c a) -> Pf (Lens c a) -> Rule -> IO ()
proveLnsRule t@(Lns c a) l r = case (evalRWST (r t l) [0] (Dyn (Pf t) l)) of
    { Just (l',_)   -> do
                        putStr "Proving get: \n"
                        getl <- reduceIO PF.optimise_pf (Fun c a) $ getof t l
                        putStrLn "="
                        getl' <- reduceIO PF.optimise_pf (Fun c a) $ getof t l'
                        print $ geq (Pf $ Fun c a) getl getl'
                        putStr "Proving create: \n"
                        createl <- reduceIO PF.optimise_pf (Fun a c) $ createof t l
                        putStrLn "="
                        createl' <- reduceIO PF.optimise_pf (Fun a c) $ createof t l'
                        print $ geq (Pf $ Fun a c) createl createl'
                        putStr "Proving put: \n"
                        putl <- writeIO "put.txt" nop (Fun (Prod a c) c) $ putof t l
                        putStrLn "="
                        putl' <- writeIO "put2.txt" nop (Fun (Prod a c) c) $ putof t l'
                        print $ geq (Pf $ Fun (Prod a c) c) putl putl'
    ; otherwise -> putStrLn "non-matching rule" }