liquidhaskell-0.8.10.7: tests/refined-classes/semigroup_desugared.hs
{-@ LIQUID "--reflection" @-}
module Semigroup where
import Prelude hiding (Semigroup(..), mappend)
infixl 3 ?
(?) :: a -> () -> a
x ? _ = x
{-# INLINE (?) #-}
infixl 3 ==.
-- {-@ reflect (==.) @-}
(==.) :: a -> a -> a
_ ==. x = x
{-# INLINE (==.) #-}
data QED = QED
-- {-@ reflect *** @-}
infixl 2 ***
x *** QED = ()
-- ==========
-- Desugaring
-- ==========
{-@
data SemigroupD a = SemigroupD {
sdMappend :: a -> a -> a
, sdLawAssociative :: x : a
-> y : a
-> z : a
-> {sdMappend (sdMappend x y) z = sdMappend x (sdMappend y z)}
}
@-}
data SemigroupD a = SemigroupD {
sdMappend :: a -> a -> a
, sdLawAssociative :: a -> a -> a -> ()
}
{-@ reflect mappendInt @-}
mappendInt :: Int -> Int -> Int
mappendInt a b = a + b
-- {-@ reflect semigroupInt @-}
-- {-@ lazy semigroupInt @-}
semigroupInt :: SemigroupD Int
semigroupInt = SemigroupD mappendInt lawAssociativeInt
-- {-@ reflect lawAssociativeInt @-}
{-@ lawAssociativeInt
:: x : Int
-> y : Int
-> z : Int
-> {mappendInt (mappendInt x y) z = mappendInt x (mappendInt y z)}
@-}
lawAssociativeInt x y z =
mappendInt (mappendInt x y) z
==. (x + y) + z
==. x + (y + z)
==. mappendInt x (mappendInt y z)
*** QED
-- JP: Why does the previous work? I expected something like the following:
--
-- {-@ lawAssociativeInt
-- :: x : Int
-- -> y : Int
-- -> z : Int
-- -> {mappend semigroupInt (mappend semigroupInt x y) z = mappend semigroupInt x (mappend semigroupInt y z)}
-- @-}
-- lawAssociativeInt x y z =
-- mappend semigroupInt (mappend semigroupInt x y) z
-- ==. (x + y) + z
-- ==. x + (y + z)
-- ==. mappend semigroupInt x (mappend semigroupInt y z)
-- *** QED
-- ======================================
-- Attempting to use desugared class laws
-- ======================================
{-@ assume lawAssociative
:: d : SemigroupD a
-> x : a
-> y : a
-> z : a
-> {sdMappend d (sdMappend d x y) z = sdMappend d x (sdMappend d y z)}
@-}
lawAssociative :: SemigroupD a -> a -> a -> a -> ()
lawAssociative _ _ _ _ = ()
{-@ testLemma
:: d : SemigroupD a
-> x : a
-> y : a
-> z : a
-> {sdMappend d (sdMappend d x y) z = sdMappend d x (sdMappend d y z) }
@-}
testLemma :: SemigroupD a -> a -> a -> a -> ()
testLemma d x y z = sdLawAssociative d x y z
-- JP: sdLawAssociative doesn't work, but replacing it with the assumed lawAssociative does.
-- {-@ testLemma'
-- :: d : SemigroupD a
-- -> w : a
-- -> x : a
-- -> y : a
-- -> z : a
-- -> {sdMappend d (sdMappend d w x) (sdMappend d y z) = sdMappend d w (sdMappend d x (sdMappend d y z)) }
-- @-}
-- testLemma' :: SemigroupD a -> a -> a -> a -> a -> ()
-- testLemma' d w x y z = lawAssociative d w x (sdMappend d y z)
-- -- sdMappend d (sdMappend d w x) r ? lawAssociative d w x r
-- -- ==. sdMappend d w (sdMappend d x r)
-- -- *** QED
--
-- where
-- r = sdMappend d y z
-- {-@ mappend
-- {-@ assume mappend
-- :: d : SemigroupD a
-- -> x : a
-- -> y : a
-- -> z : {a | z = sdMappend d x y}
-- @-}
--
-- {-@ reflect mappend @-}
-- mappend :: SemigroupD a -> a -> a -> a
-- mappend d x y = sdMappend d x y
--
-- -- {-@ reflect lawAssociative @-}
-- -- {-@ lawAssociative
-- {-@ assume lawAssociative
-- :: d : SemigroupD a
-- -> x : a
-- -> y : a
-- -> z : a
-- -> {mappend d (mappend d x y) z = mappend d x (mappend d y z)}
-- @-}
-- lawAssociative :: SemigroupD a -> a -> a -> a -> ()
-- lawAssociative d x y z = sdLawAssociative d x y z