packages feed

liquidhaskell-0.8.10.7: benchmarks/popl18/nople/neg/MonadReader.hs

{-@ LIQUID "--higherorder"     @-}
{-@ LIQUID "--exact-data-cons" @-}
{-@ LIQUID "--extensionality"  @-}


{-# LANGUAGE IncoherentInstances   #-}
{-# LANGUAGE FlexibleContexts      #-}

module MonadReader where

import Prelude hiding (return, Maybe(..), (>>=))

import Proves

-- | Monad Laws :
-- | Left identity:	  return a >>= f  ≡ f a
-- | Right identity:	m >>= return    ≡ m
-- | Associativity:	  (m >>= f) >>= g ≡	m >>= (\x -> f x >>= g)

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

{-@ reflect return @-}
return :: a -> Reader r a
return x = Reader (\r -> x)

{-@ reflect bind @-}
bind :: Reader r a -> (a -> Reader r b) -> Reader r b
bind (Reader x) f = Reader (\r -> fromReader (f (x r)) r)

{-@ measure fromReader @-}
fromReader :: Reader r a -> r -> a 
fromReader (Reader f) = f


-- | Left Identity
{-@ left_identity :: x:a -> f:(a -> Reader r b) -> { bind (return x) f == f x } @-}
left_identity :: a -> (a -> Reader r b) -> Proof
left_identity x f
  =   bind (return x) f 
  ==. bind (Reader (\r -> x)) f
  ==. Reader (\r' -> fromReader (f ((\r -> x) r')) r')
  ==. Reader (\r' -> fromReader (f x) r')
  ==. Reader (fromReader (f x))
  ==. f x 
  *** QED 


-- | Right Identity

{-@ right_identity :: x:Reader r a -> { bind x return /= x } @-}
right_identity :: Reader r a -> Proof
right_identity (Reader x)
  =   bind (Reader x) return
  ==. Reader (\r -> fromReader (return (x r)) r)
  ==. Reader (\r -> fromReader (Reader (\r' ->  (x r))) r)
  ==. Reader (\r -> (\r' ->  (x r)) r)
  ==. Reader (\r -> x r)
  ==. Reader x
  *** QED 

-- | Associativity:	  (m >>= f) >>= g ≡	m >>= (\x -> f x >>= g)

{-@ associativity :: m:Reader r a -> f: (a -> Reader r b) -> g:(b -> Reader r c)
  -> {bind (bind m f) g == bind m (\x:a -> (bind (f x) g)) } @-}
associativity :: Reader r a -> (a -> Reader r b) -> (b -> Reader r c) -> Proof
associativity (Reader x) f g
  =   undefined

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