grisette-0.3.0.0: src/Grisette/Core/Data/Class/Solvable.hs
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE ViewPatterns #-}
-- |
-- Module : Grisette.Core.Data.Class.Solvable
-- Copyright : (c) Sirui Lu 2021-2023
-- License : BSD-3-Clause (see the LICENSE file)
--
-- Maintainer : siruilu@cs.washington.edu
-- Stability : Experimental
-- Portability : GHC only
module Grisette.Core.Data.Class.Solvable
( -- * Solvable type interface
Solvable (..),
pattern Con,
)
where
import Control.DeepSeq
import Data.Hashable
import Data.String
import Data.Typeable
import Language.Haskell.TH.Syntax
-- $setup
-- >>> import Grisette.Core
-- >>> import Grisette.IR.SymPrim
-- | The class defines the creation and pattern matching of solvable type
-- values.
class (IsString t) => Solvable c t | t -> c where
-- | Wrap a concrete value in a symbolic value.
--
-- >>> con True :: SymBool
-- true
con :: c -> t
-- | Extract the concrete value from a symbolic value.
--
-- >>> conView (con True :: SymBool)
-- Just True
--
-- >>> conView (ssym "a" :: SymBool)
-- Nothing
conView :: t -> Maybe c
-- | Generate simply-named symbolic constants.
--
-- Two symbolic constants with the same name are the same symbolic constant,
-- and will always be assigned with the same value by the solver.
--
-- >>> ssym "a" :: SymBool
-- a
-- >>> (ssym "a" :: SymBool) == ssym "a"
-- True
-- >>> (ssym "a" :: SymBool) == ssym "b"
-- False
-- >>> (ssym "a" :: SymBool) &&~ ssym "a"
-- a
ssym :: String -> t
-- | Generate indexed symbolic constants.
--
-- Two symbolic constants with the same name but different indices are
-- not the same symbolic constants.
--
-- >>> isym "a" 1 :: SymBool
-- a@1
isym :: String -> Int -> t
-- | Generate simply-named symbolic constants with some extra information for
-- disambiguation.
--
-- Two symbolic constants with the same name but different extra information
-- (including info with different types) are considered to be different.
--
-- >>> sinfosym "a" "someInfo" :: SymInteger
-- a:"someInfo"
sinfosym :: (Typeable a, Ord a, Lift a, NFData a, Show a, Hashable a) => String -> a -> t
-- | Generate indexed symbolic constants with some extra information for
-- disambiguation.
--
-- Two symbolic constants with the same name and index but different extra
-- information (including info with different types) are considered to be
-- different.
--
-- >>> iinfosym "a" 1 "someInfo" :: SymInteger
-- a@1:"someInfo"
iinfosym :: (Typeable a, Ord a, Lift a, NFData a, Show a, Hashable a) => String -> Int -> a -> t
-- | Extract the concrete value from a solvable value with 'conView'.
--
-- >>> case con True :: SymBool of Con v -> v
-- True
pattern Con :: (Solvable c t) => c -> t
pattern Con c <-
(conView -> Just c)
where
Con c = con c