2

Basically I'm wondering, is there any way to write a function of the following type with the SBV library:

(SBV a, SBV b) -> SBV (a,b)

This seems like it should be possible: if we have two symbolic values, we can make a new symbolic value, as a concrete pair whose elements are either the symbolic or concrete values of the two inputs. But I can't find anything like this, and the SBV type does not have its constructors exposed.

Is this possible?

jmite
  • 8,171
  • 6
  • 40
  • 81
  • 1
    Does `STuple` not meet your needs? – Bob Dalgleish Jul 03 '19 at 18:37
  • From skimming the source code, it [looks like](http://hackage.haskell.org/package/sbv-8.3/docs/src/Data.SBV.Core.Concrete.html#CVal) a concrete value is always *fully* concrete. The `CTuple` constructor contains a list of `CVal`s, not `SBV`s. That is, you can't have a concrete tuple containing a symbolic value. – Benjamin Hodgson Jul 03 '19 at 18:39
  • 1
    @BobDalgleish But `type STuple a b = SBV (a, b)`, so the question remains exactly the same even if `STuple` does meet their needs! – Daniel Wagner Jul 03 '19 at 22:07
  • What do you want to do with your `SBV (a,b)` that you cannot do with an `(SBV a, SBV b)`? (If the answer is "use `(.==)` or similar with another `SBV (a, b)`", can you modify your code to change the other thing to an `(SBV a, SBV b)` instead?) – Daniel Wagner Jul 03 '19 at 22:10
  • @DanielWagner I need an uninterpreted function with multiple arguments, where the number of arguments is not known statically. I've been messing around with existential types and such, but I'm not sure that it's even possible with SBV. I'd used SimpleSMT but it's cripplingly slow. – jmite Jul 03 '19 at 22:18
  • @DanielWagner It is true that `SBV (a, b)` and `(SBV a, SBV b)` have pretty much the same expressive power; and indeed `tuple` and `untuple` functions form an isomorphism between them. But in practice, having `SBV (a, b)` is really nice as it cuts down on boilerplate, and also it directly maps to actual SMT-Lib tuples. They are just much more convenient in general. – alias Jul 03 '19 at 23:30

1 Answers1

3

Sounds like you need the tuple function. Here's an example:

import Data.SBV
import Data.SBV.Tuple

tup :: (SymVal a, SymVal b) => (SBV a, SBV b) -> SBV (a, b)
tup = tuple

tst :: Predicate
tst = do x <- sInteger "x"
         y <- sInteger "y"
         z <- sTuple "xy"

         return $ tup (x, y) .== z

Of course, tuple itself can handle arity upto 8; the above is just one instantiation at the exact type you wanted. We have:

$ ghci a.hs
GHCi, version 8.6.4: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Main             ( a.hs, interpreted )
Ok, one module loaded.
*Main> sat tst
Satisfiable. Model:
  x  =     0 :: Integer
  y  =     1 :: Integer
  xy = (0,1) :: (Integer, Integer)

There's also the untuple function that goes in the other direction. They are both in the Data.SBV.Tuple module that you have to explicitly import. (You can also find lens-like accessors in the same module, which lets you write, ^._1, ^._2 etc. to extract fields of tuples; as in z^._2 for the above example.)

alias
  • 28,120
  • 2
  • 23
  • 40