packages feed

liquidhaskell-0.8.10.7: benchmarks/popl18/nople/pos/FunctorReader.hs

{-@ LIQUID "--higherorder"     @-}
{-@ LIQUID "--exact-data-cons" @-}
{-@ LIQUID "--alphaequivalence" @-}
{-@ LIQUID "--betaequivalence"  @-}

{-# LANGUAGE IncoherentInstances #-}
{-# LANGUAGE FlexibleContexts    #-}
module FunctorList where

import Prelude hiding (fmap, id)

import Proves
import Helper 

-- | Functor Laws :
-- | fmap-id fmap id ≡ id
-- | fmap-distrib ∀ g h . fmap (g ◦ h) ≡ fmap g ◦ fmap h

{-@ data Reader r a = Reader { runIdentity :: r -> a } @-}
data Reader r a     = Reader { runIdentity :: r -> a }

{-@ reflect fmap @-}
fmap :: (a -> b) -> Reader r a -> Reader r b
fmap f (Reader rd) = Reader (\r -> f (rd r))

{-@ reflect id @-}
id :: a -> a
id x = x

{-@ reflect compose @-}
compose :: (b -> c) -> (a -> b) -> a -> c
compose f g x = f (g x)

-- | Identity 

{-@ fmap_id :: xs:Reader r a -> { fmap id xs == id xs } @-}
fmap_id :: Arg r => Reader r a  ->  Proof
fmap_id (Reader x) 
   =   fmap id (Reader x)
   ==. Reader (\r -> id (x r))
   ==. Reader (\r -> x r)       ? fmap_id_helper x  
   ==. Reader x                 ? lambda_expand x 
   ==. id (Reader x)
   *** QED
 

{-@ fmap_id_helper ::  f:(r -> a)
            -> { (\r:r -> (id (f r))) == (\r:r-> (f (r))) } @-}
fmap_id_helper :: (Arg r) => (r -> a) ->  Proof
fmap_id_helper f
   =    ((\r -> id (f r)) 
   =*=: (\r -> f r)) (fmap_id_helper_body f)
   *** QED 


{-@ fmap_id_helper_body 
  :: f:(r -> a) -> r:r 
  -> {(id (f r) == f r) 
      && ((\r:r -> (id (f r))) (r) == id (f r))  
      && ((\r:r-> (f r)) (r) == f r) 
      } @-} 
fmap_id_helper_body :: Arg r => (r -> a) -> r -> Proof 
fmap_id_helper_body f r 
  = id (f r) ==. f r *** QED 



{-@ fmap_distrib :: f:(a -> a) -> g:(a -> a) -> xs:Reader r a
               -> { fmap  (compose f g) xs == (compose (fmap f) (fmap g)) (xs) } @-}
fmap_distrib :: Arg r => (a -> a) -> (a -> a) -> Reader r a -> Proof
fmap_distrib f g (Reader x)
  =   fmap (compose f g) (Reader x)
  ==. Reader (\r -> (compose f g) (x r))     
  ==. Reader (\r -> f ( g (x r)))            ? fmap_distrib_helper f g x 
  ==. Reader (\r -> f ((\w -> g (x w)) r))
  ==. fmap f (Reader (\w -> g (x w)))
  ==. fmap f (fmap g (Reader x))
  ==. (compose (fmap f) (fmap g)) (Reader x)
  *** QED





fmap_distrib_helper :: Arg r => (a -> a) -> (a -> a) -> (r -> a) -> Proof 
{-@ fmap_distrib_helper
  :: f:(a -> a) -> g:(a -> a) -> x:(r -> a) 
  -> {(\r:r -> (compose f g) (x r)) == (\r:r -> (f (g (x r))) ) } @-}
fmap_distrib_helper f g x 
  =   ((\r -> (compose f g) (x r)) 
  =*=: (\r -> f (g (x r)))) (fmap_distrib_helper' f g x)
  *** QED 



fmap_distrib_helper' :: Arg r => (a -> a) -> (a -> a) -> (r -> a) -> r -> Proof 
{-@ fmap_distrib_helper' 
  :: f:(a -> a) -> g:(a -> a) -> x:(r -> a) -> r:r
  -> { (\r:r -> (compose f g) (x r)) (r) == (\r:r -> (f (g (x r)))) (r) } @-}
fmap_distrib_helper' f g x r  
  =   (compose f g) (x r) 
  ==. f (g (x r))
  *** QED 



{-@ qual :: f:(r -> a) -> {v:Reader r a | v == Reader f} @-}
qual :: (r -> a) -> Reader r a 
qual = Reader