Closed LeventErkok closed 1 year ago
Here's one attempt to do generic types. Though how this fits into existing SBV requires more experimentation:
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wall -Werror #-}
module T where
import qualified GHC.Generics as G
data SBV a = SBV a
deriving Show
type family SymRep a where
SymRep Int = Int
SymRep a = G.Rep a a
class SymVal a where
literal :: a -> SBV (SymRep a)
unliteral :: SBV (SymRep a) -> Maybe a
default literal :: (G.Generic a, SymRep a ~ G.Rep a f) => a -> SBV (SymRep a)
literal a = SBV (G.from a)
default unliteral :: (G.Generic a, SymRep a ~ G.Rep a f) => SBV (SymRep a) -> Maybe a
unliteral (SBV a) = Just (G.to a)
data T = T1 { a :: Int
, b :: Int
}
| T2 Bool
deriving (Show, G.Generic, SymVal)
instance SymVal Int where
literal = SBV
unliteral (SBV i) = Just i
You can try:
*T> literal (T1 2 3)
SBV (M1 {unM1 = L1 (M1 {unM1 = M1 {unM1 = K1 {unK1 = 2}} :*: M1 {unM1 = K1 {unK1 = 3}}})})
*T> unliteral (literal (T1 2 3)) :: Maybe T
Just (T1 {a = 2, b = 3})
This requires changing SymVal
class, so representation type can differ from the type itself. Which is probably how it should've been designed in the first place. Alas, too late for that,.
Here's an example. Note that this is a bit mouthful. It is possible to define
mkConstraint
/skolemize
etc. to make this look pretty, but unless we add some generic way of making general product types usable this way, it's probably too advanced for most users. Something to think about.At the least, we should put this into documentation somewhere:
This prints: