packages feed

liquidhaskell-0.8.0.2: tests/pos/LF326.hs

#!/usr/bin/env stack
-- stack --resolver lts-9.2 exec liquid --package process --install-ghc

{-@ LIQUID "--higherorder"       @-}
{-@ LIQUID "--exact-data-cons"   @-}
{- LIQUID "--automatic-instances=liquidinstances" @-}

{-# LANGUAGE GADTs               #-}
module Foo where 

import Prelude hiding (Maybe (..), Either (..))
import System.Process
type Heap = Map Int (Maybe Val)

-- Heap Parital Order:
--------------------------------------------------------------------------------
data HeapLteProp where
  HeapLte :: Heap -> Heap -> HeapLteProp

-- | Partial ordering on the `Heap`. Read as "definedness"
data HeapLte where
  HeapRefl :: Heap -> HeapLte
  HeapTrans :: Heap -> Heap -> Heap
            -> HeapLte -> HeapLte
            -> HeapLte
  HeapAdd :: Heap -> Int -> Maybe Val
          -> HeapLte
{-@ data HeapLte where
    HeapRefl  :: h:Heap -> Prop (HeapLte h h)
  | HeapTrans :: h1:Heap -> h2:Heap -> h3:Heap
              -> Prop (HeapLte h1 h2)
              -> Prop (HeapLte h2 h3)
              -> Prop (HeapLte h1 h3)
  | HeapAdd   :: h:Heap -> k:Int -> val:(Maybe Val)
              -> Prop (HeapLte h (Record k val h))
@-}
{-@ measure prop :: a -> b           @-}
{-@ type Prop E = {v:_ | prop v = E} @-}

-- Maybe
--------

{-@ data MyEither a b = Left {selectLeft :: a}  | Right {selectRight :: b}  @-}
data MyEither a b = Left { selectLeft :: a }  | Right { selectRight :: b } 
data Maybe a = Just a | Nothing

{-@ reflect join @-}
join (Just (Just x)) = Just x
join _               = Nothing

{-@ reflect $$ @-}
f $$ x = f x

-- Maps
---------

{-@ data Map [mlen] k v = Empty | Record {mKey :: k, mVal :: v, mRest :: Map k v} @-}
data Map k v = Empty
         | Record k v (Map k v)

{-@ measure mlen @-}
{-@ mlen :: Map k v -> Nat @-}
mlen :: Map k v-> Int
mlen Empty          = 0
mlen (Record k v r) = 1 + mlen r

{-@ reflect update @-}
update :: Map k v -> k -> v -> Map k v
update m k v = Record k v m

{-@ reflect find @-}
find :: Eq k => k -> Map k v -> Maybe v
find key  Empty          = Nothing
find key (Record k v r)
  | k == key            = Just v
  | otherwise           = find key r

{-@ reflect delete @-}
delete :: Eq k => k -> Map k v -> Map k v
delete key Empty          = Empty
delete key (Record k v r)
  | k == key            = delete key r
  | otherwise           = Record k v (delete key r)

{-@ reflect insertWith @-}
insertWith :: Eq k => (v -> v -> v) -> k -> v -> Map k v -> Map k v
insertWith _ _ _ Empty  = Empty
insertWith f key val (Record k v r)
  | k == key            = Record k (f v val) r
  | otherwise           = Record k v (insertWith f key val r)

-- List
--------

{-@ reflect app @-}
app :: [a] -> [a] -> [a]
app (x:xs) ys = x:(app xs ys)
app [] ys     = ys

{-@ reflect fmapList @-}
fmapList :: (a -> b) -> [a] -> [b]
fmapList f (x:xs) = f x : fmapList f xs
fmapList _ [] = []

-- step
--------------------------------------------------------------------------------
type Val = Double -- Int

data IVar a = IVar Int

data Trace = Get (IVar Val) (Val -> Trace)
           | Put (IVar Val) Val Trace
           | New (IVar Val -> Trace)
           | Fork Trace Trace
           | Done

data Exn = MultiplePut Val Int Val
         | Deadlock (Map Int [Val -> Trace])
         | HeapExn

instance Eq Exn where
  MultiplePut _ _ _ == MultiplePut _ _ _ = True
  Deadlock _ == Deadlock _ = True
  HeapExn == HeapExn = True
  _ == _ = False

{-@ reflect step @-}
step :: (Trace, [Trace]) -> Map Int [Val -> Trace] -> Int -> Heap
     -> MyEither Exn ([Trace], Map Int [Val -> Trace], Int,  Heap)
step (trc, others) blkd cntr heap =
  case trc of
    Done            -> Right (others, blkd, cntr, heap)
    Fork t1 t2      -> Right (t1 : t2 : others, blkd, cntr, heap)
    New k           -> Right (k (IVar cntr) : others, blkd, cntr + 1, Record cntr Nothing heap)
    Get (IVar ix) k -> case join (find ix heap) of
                         Nothing -> Right (others, insertWith app ix [k] blkd, cntr, heap)
                         Just v  -> Right (k v : others, blkd, cntr, heap)
    Put (IVar ix) v t2 -> let heap' = Record ix (Just v) heap in
                          case join (find ix heap) of
                            Just v0 -> Left (MultiplePut v ix v0)
                            Nothing -> case find ix blkd of
                              Nothing -> Right (t2 : others, blkd, cntr, heap')
                              Just ls -> Right (t2 : app ( fmapList ($$ v) ls ) others, delete ix blkd, cntr, heap')

-- Theorems
-------------

{-@ reflect select4of4 @-}
select4of4 (_,_,_,h) = h


{-@ theoremMonotonic :: a:(Trace,[Trace]) -> b:( Map Int [Val -> Trace]) -> c:Int -> h:Heap
                     -> h':{v:Heap | v = select4of4 (selectRight (step a b c h))}
                     -> Prop ( HeapLte h h' )
  @-}
theoremMonotonic :: (Trace, [Trace]) ->  Map Int [Val -> Trace] -> Int -> Heap -> Heap -> ()
theoremMonotonic x y = undefined