packages feed

liquidhaskell-0.8.10.7: tests/ple/pos/T1302b.hs

-- https://github.com/ucsd-progsys/liquidhaskell/issues/1302
--
{-# LANGUAGE EmptyDataDecls, GADTs, ExistentialQuantification #-}

{-@ LIQUID "--no-adt" 	      @-}
{-@ LIQUID "--exact-data-con" @-}
{-@ LIQUID "--higherorder"    @-}
{-@ LIQUID "--no-termination" @-}
{-@ LIQUID "--no-totality"    @-}
{-@ LIQUID "--ple"            @-} 

module Field where

import Prelude hiding (sequence, mapM, filter)
-- import qualified Data.Set as Set

data User = User Integer
  deriving (Show, Eq)

{-@ reflect admin @-}
admin = User 0

{-@ data Tagged a <p :: User -> Bool> = Tagged { content :: a } @-}
data Tagged a = Tagged { content :: a }



{-@ data variance Tagged covariant contravariant @-}

{-@ output :: forall <p :: User -> Bool>.
             msg:Tagged <p> a 
          -> User<p>
          -> ()
@-}

data RefinedPersistFilter = EQUAL



{-@ data RefinedFilter record typ <p :: User -> Bool> = RefinedFilter
      { refinedFilterField  :: EntityField record typ
      , refinedFilterValue  :: typ
      , refinedFilterFilter :: RefinedPersistFilter
      } 
  @-}

{-@ data variance RefinedFilter covariant covariant contravariant @-}
data RefinedFilter record typ = RefinedFilter
    { refinedFilterField  :: EntityField record typ
    , refinedFilterValue  :: typ
    , refinedFilterFilter :: RefinedPersistFilter
    } 

{-@ filter :: f:(a -> Bool) -> [a] -> [{v:a | f v}] @-}
filter :: (a -> Bool) -> [a] -> [a]
filter f (x:xs)
  | f x         = x : filter f xs
  | otherwise   =     filter f xs
filter _ []     = []


{-@ reflect evalQCreditCardNumber @-}
evalQCreditCardNumber :: RefinedPersistFilter -> Int -> Int -> Bool
evalQCreditCardNumber EQUAL filter given = given == filter

{-@ reflect evalQCreditCardHolder @-}
evalQCreditCardHolder :: RefinedPersistFilter -> [Char] -> [Char] -> Bool
evalQCreditCardHolder EQUAL filter given = given == filter

{-@ reflect evalQCreditCard @-}
evalQCreditCard :: RefinedFilter CreditCard typ -> CreditCard -> Bool
evalQCreditCard filter x = case refinedFilterField filter of
    CreditCardNumber -> evalQCreditCardNumber (refinedFilterFilter filter) (refinedFilterValue filter) (creditCardNumber x)
    CreditCardHolder -> evalQCreditCardHolder (refinedFilterFilter filter) (refinedFilterValue filter) (creditCardHolder x)

{-@ reflect evalQsCreditCard @-}
evalQsCreditCard :: [RefinedFilter CreditCard typ] -> CreditCard -> Bool
evalQsCreditCard (f:fs) x = evalQCreditCard f x && (evalQsCreditCard fs x)
evalQsCreditCard [] _ = True

{-@ assume selectCreditCard :: forall <p :: User -> Bool>. f:[RefinedFilter<p> CreditCard typ]
                -> Tagged<p> [{v:CreditCard | evalQsCreditCard f v}] @-}
selectCreditCard ::
      [RefinedFilter CreditCard typ]
      -> Tagged [CreditCard]
selectCreditCard fs = undefined

-- BUG: why does 'RefinedFilter x2 x1' show up in the output, and not 'RefinedFilter CreditCardNumber x2 x1'?

{-@ reflect filterCreditCardNumber @-}
{-@ filterCreditCardNumber :: RefinedPersistFilter -> Int -> RefinedFilter<{\u -> u == admin}> CreditCard Int @-}
filterCreditCardNumber :: RefinedPersistFilter -> Int -> RefinedFilter CreditCard Int
filterCreditCardNumber f v = RefinedFilter CreditCardNumber v f

{-@ filterCreditCardHolder :: RefinedPersistFilter -> [Char] -> RefinedFilter<{\u -> u == admin}> CreditCard [Char] @-}
filterCreditCardHolder :: RefinedPersistFilter -> [Char] -> RefinedFilter CreditCard [Char]
filterCreditCardHolder f v = RefinedFilter CreditCardHolder v f

output :: Tagged a -> User -> ()
output = undefined

data CreditCard = CreditCard { creditCardNumber :: Int, creditCardHolder :: [Char]}
{-@
data CreditCard = CreditCard
	{ creditCardNumber :: Int
	, creditCardHolder :: [Char]
	}
@-}

{-@
data EntityField Creditcard typ where 
   Field.CreditCardNumber :: EntityField CreditCard {v:_ | True}
   Field.CreditCardHolder :: EntityField CreditCard {v:_ | True}
@-}

{-@ assume error :: [Char] -> a @-} 

data EntityField a b where
  CreditCardNumber :: EntityField CreditCard Int
  CreditCardHolder :: EntityField CreditCard [Char]

{-@ reflect testFilter @-}
{-@ testFilter :: RefinedFilter <{\u -> u == admin}> CreditCard Int @-} 
testFilter = filterCreditCardNumber EQUAL 3

{-@ selectTaggedData :: () -> Tagged<{\u -> u == admin}> [{v:CreditCard | creditCardNumber v == 3}] @-}
selectTaggedData :: () -> Tagged [CreditCard]
selectTaggedData () = selectCreditCard [testFilter]
-- selectTaggedData () = selectCreditCard [RefinedFilter CreditCardNumber 3 EQUAL]