{-# LANGUAGE BangPatterns #-}
module Algebra.Heyting.CounterExample where
import Data.Set (Set)
import qualified Data.Set as Set
import Text.Printf (printf)
import Algebra.Lattice (top)
import Algebra.Lattice.Lifted (Lifted)
import qualified Algebra.Lattice.Lifted as Lifted
import Algebra.Lattice.Levitated (Levitated)
import qualified Algebra.Lattice.Levitated as Levitated
import Algebra.Lattice.Op (Op (..))
type CounterExample a = Lifted (Op (Set a))
fmapCounterExample
:: (Ord a, Ord b)
=> (a -> b)
-> CounterExample a
-> CounterExample b
fmapCounterExample = fmap . fmap . Set.map
counterExample :: e -> CounterExample e
counterExample e = Lifted.Lift (Op (Set.singleton e))
fromBool :: Ord e => e -> Bool -> CounterExample e
fromBool e False = counterExample e
fromBool _ True = top
toBool :: CounterExample e -> Bool
toBool (Lifted.Lift (Op s)) | Set.null s
= True
toBool _ = False
foldMapCounterExample
:: (Ord e, Monoid m)
=> (e -> m)
-> CounterExample e
-> Levitated m
foldMapCounterExample f (Lifted.Lift (Op s)) | Set.null s = Levitated.Top
| otherwise = Levitated.Levitate (foldMap f s)
foldMapCounterExample _ Lifted.Bottom = Levitated.Bottom
fromCounterExample :: Show a => CounterExample a -> Levitated String
fromCounterExample Lifted.Bottom = Levitated.Bottom
fromCounterExample (Lifted.Lift (Op s)) | Set.null s
= Levitated.Top
| otherwise
= Levitated.Levitate (Set.foldl' go "" s)
where
go "" b = show b
go !a b = printf "%s, %s" a (show b)
fromCounterExample' :: Show a => CounterExample a -> Maybe String
fromCounterExample' ce = case fromCounterExample ce of
Levitated.Top -> Nothing
Levitated.Levitate s -> Just s
Levitated.Bottom -> Just ""
annotate :: Ord e => e -> CounterExample e -> CounterExample e
annotate e Lifted.Bottom = counterExample e
annotate _ es = es
(===) :: (Ord e, Eq a) => a -> a -> CounterExample e
a === b = if a == b then Lifted.Lift (Op Set.empty) else Lifted.Bottom
infixr 4 ===