In SML's grammar
Programs
prog ::= dec core declaration
functor fctbind functor declaration
signature sigbind signature declaration
empty
prog1 ⟨;⟩ prog2 sequence
fctbind ::= id1 ( id2 : sig ) ⟨:⟨>⟩ sig⟩ = str ⟨and fctbind⟩ plain
id ( spec ) ⟨:⟨>⟩ sig⟩ = str ⟨and fctbind⟩ opened
sigbind ::= id = sig ⟨and sigbind⟩ signature
Why
val a = 1
val b = 2;
a
b
has error between a and b, but not between the two val declarations?
$sml < main.sml
Standard ML of New Jersey v110.78 [built: Thu Aug 31 03:45:42 2017]
- val a = 1 : int
val b = 2 : int
= stdIn:4.1-5.2 Error: operator is not a function [tycon mismatch]
operator: int
in expression:
a b
Thanks.
In
val a = 1
val b = 2
All you've done is bind two variables, corresponding to the rules
dec ::= val ⟨var⟩(,) valbind, dec ::= dec1 ⟨;⟩ dec2, and at top level,
prog ::= dec.
Then in
a
b
You're actually attempting to apply a to b (exp ::= exp1 exp2 (application)). It might be simpler to see it as the equivalently written
a b
However, a doesn't have a function type, hence the error operator is not a function. It's unclear what you're actually attempting to do with a and b.
Related
For example, I got a constraint: "(number < 10) && (name == "hello")";
I can do the following now:
context c;
expr number= c.int_const(number);
expr name = c->string_val(name.c_str());
expr constrain = ***procedure***("(number < 10) && (name == \"hello\")");
How can I implement this procedure()?
there is an incomplete and unproofed answer in Use a C++ string in z3::expr?, and I still can not figure out how to implement it?
I am very eagered and appreciateed for your help! Thanks!
Try:
#include <z3++.h>
using namespace z3;
using namespace std;
int main ()
{
context c;
expr number = c.int_const("number");
expr name = c.constant(c.str_symbol("name"), c.string_sort());
expr hello = c.string_val("hello");
expr constraint = number < 10 && name == hello;
solver s(c);
s.add(constraint);
cout << s.check() << "\n";
cout << s.get_model() << "\n";
return 0;
};
Assuming you put the above in a file called a.cpp, you compile it like this:
$ g++ -std=c++11 a.cpp -l z3
And when run, it produces:
sat
(define-fun number () Int
9)
(define-fun name () String
"hello")
Using higher-level APIs
As you no doubt noticed, programming z3 in C/C++ is very verbose and terribly error prone. Unless you've some other reason to use C/C++, I'd recommend using a higher-level API, such as Python or Haskell, which simplifies programming in z3 to a great extent.
Python
For instance, you'd code your problem in Python like this:
from z3 import *
number = Int('number')
name = String('name')
s = Solver()
s.add(number < 10, name == "hello")
print(s.check())
print(s.model())
producing:
sat
[number = 9, name = "hello"]
Haskell
And in Haskell, it would look like:
import Data.SBV
ex :: IO SatResult
ex = sat $ do number <- sInteger "number"
name <- sString "name"
constrain $ number .< 10 .&& name .== literal "hello"
producing:
*Main> ex
Satisfiable. Model:
number = 9 :: Integer
name = "hello" :: String
Summary
Long story short, programming z3 in C/C++—while entirely possible—is something that's best avoided if you can use a higher-level interface. If you must stick to C/C++, be sure to study the API: https://z3prover.github.io/api/html/namespacez3.html
For example, I want to cast nat to seq of char in VDM++.
In the code below, I want operation setValueOfX to return "X is {value of q}", if q is of type nat and q < 3.
class A1
instance variables
private x : nat := 0;
operations
public setValueOfX : nat ==> seq of char
setValueOfX(q) ==
(
if is_nat(q) and q < 3
then
(
x := q;
-- The following line doesn't work
-- return "X is " ^ q;
)
else
return "Invalid value! Value of x must be more than 0 and less than 3.";
);
end A1
I've tried using ^ but I got the following error:
Error[207] : Rhs of '^' is not a sequence type
act : nat
exp : ( seq1 of # | [] )
No, you can't implicitly convert values like that in VDM.
If you just want to see the result in a textural form, you could look at the IO library, which lets you "print" a mixture of types to the console. Alternatively, if you must return a string, you could specify a function that converts a nat to a decimal string, and the return "Result is" ^ nat2str(q).
I'm using fscheck to write some unite tests and I would like to narrow down the range of decimal automatically generated and that regardless of the parameter I'm passing. What I mean by that is that let's say I have the types below:
decimal
DecimalHolder
Nested records containing decimal fields
DU with cases with decimal fields
Without having something to define an arbitrary for each single type, just that down the line in the generation if there a decimal it must say be between 0 and 300,000.
module Tests
open Xunit
open FsCheck.Xunit
open Swensen.Unquote
let addDecimals a b: decimal =
a + b
[<Property>]
let ``test adding two decimals`` a b =
let actual = addDecimals a b
let expected = a + b
test<# actual = expected #>
type DecimalHolder =
{ Value: decimal }
let addDecimalHolders a b =
{ Value = a.Value + b.Value }
[<Property>]
let ``test adding two decimal holders`` a b =
let actual = addDecimalHolders a b
let expected = { Value = a.Value + b.Value }
test<# actual = expected #>
type DecimalStuff =
| Value of decimal
| Holder of DecimalHolder
| Holders of DecimalHolder list
// Whatever
etc.
How can I achieve that?
Ok actually the Arbitrary definition works recursively across parameters types was enough:
module Tests
open Xunit
open FsCheck.Xunit
open Swensen.Unquote
type NotBigPositiveDecimalArbitrary =
static member NotBigPositiveDecimal() =
Gen.choose (1, 500)
|> Gen.map (fun x -> decimal x)
|> Arb.fromGen
let addDecimals a b: decimal =
a + b
[<Property(Arbitrary = [| typeof<NotBigPositiveDecimalArbitrary> |])>]
let ``test adding two decimals`` a b =
let actual = addDecimals a b
let expected = a + b
test<# actual = expected #>
type DecimalHolder =
{ Value: decimal }
let addDecimalHolders a b =
{ Value = a.Value + b.Value }
[<Property(Arbitrary = [| typeof<NotBigPositiveDecimalArbitrary> |])>]
let ``test adding two decimal holders`` a b =
let actual = addDecimalHolders a b
let expected = { Value = a.Value + b.Value }
test<# actual = expected #>
Given the following code:
require "big"
alias Type = Nil | String | Bool | Int32 | BigFloat | Array(Type) | Hash(String | Symbol, Type)
alias HOpts = Hash(String | Symbol, Type)
ctx = HOpts.new
ctx["test_int"] = 1
ctx["test_s"] = "hello"
c1 = Hash(String, Type).new
ctx["stuff"] = c1
ctx["stuff"]["foo"] = { "bar" => 1 }
I get:
Error in test.cr:13: instantiating 'Hash(String | Symbol, Type)#[]=(String, Hash(String, Type))'
ctx["stuff"] = c1
^
in /opt/crystal/src/hash.cr:43: instantiating 'insert_in_bucket(Int32, String, Hash(String, Type))'
entry = insert_in_bucket index, key, value
^~~~~~~~~~~~~~~~
in /opt/crystal/src/hash.cr:842: instantiating 'Hash::Entry(String | Symbol, Type)#value=(Hash(String, Type))'
entry.value = value
^~~~~
in /opt/crystal/src/hash.cr:881: expanding macro
property value : V
^
in macro 'property' expanded macro: macro_83313872:567, line 10:
1.
2.
3.
4. #value : V
5.
6. def value : V
7. #value
8. end
9.
> 10. def value=(#value : V)
11. end
12.
13.
14.
15.
instance variable '#value' of Hash::Entry(String | Symbol, Type) must be Type, not Hash(String, Type)
I would expect to be able to create any kind of nested hash but it does not work.
There's a couple of things wrong here.
The type of c1 is Hash(String, Type) which is not one of the types of the Type union. Hash(String, Type) is not compatible with Hash(String | Symbol, Type).
Either include Hash(String, Type) in the Type union, or give c1 the type Hash(String | Symbol, Type) (i.e. HOpts):
c1 = HOpts.new
You will also have another error on this line of code:
ctx["stuff"]["foo"] = { "bar" => 1 }
ctx["stuff"] will return an object of type Type and not a hash as you expect. If you know for certain that ctx["stuff"] is a hash (which we do from this example) then you need to restrict its type. Also { "bar" => 1 } is of type Hash(String, Int32) and not Hash(String, Type), so you need to specify this too:
ctx["stuff"].as(HOpts)["foo"] = HOpts{ "bar" => 1 }
I am new to OCaml. I installed Z3 module as mentioned in this link
I am calling Z3 using the command:
ocamlc -custom -o ml_example.byte -I ~/Downloads/z3-unstable/build/api/ml -cclib "-L ~/Downloads/z3-unstable/build/ -lz3" nums.cma z3ml.cma $1
where $1 is replaced with file name.
type loc = int
type var = string
type exp =
| Mul of int * exp
| Add of exp * exp
| Sub of exp * exp
| Const of int
| Var of var
type formula =
| Eq of exp * exp
| Geq of exp
| Gt of exp
type stmt =
| Assign of var * exp
| Assume of formula
type transition = loc * stmt * loc
module OrdVar =
struct
type t = var
let compare = Pervasives.compare
end
module VarSets = Set.Make( OrdVar )
type vars = VarSets.t
module OrdTrans =
struct
type t = transition
let compare = Pervasives.compare
end
module TransitionSets = Set.Make( OrdTrans )
type transitionSet = TransitionSets.t
type program = vars * loc * transitionSet * loc
let ex1 () : program =
let vset = VarSets.empty in
let vset = VarSets.add "x" vset in
let vset = VarSets.add "y" vset in
let vset = VarSets.add "z" vset in
let ts = TransitionSets.empty in
(* 0 X' = X + 1 *)
let stmt1 = Assign( "x", Add( Var("x"), Const(1) ) ) in
let tr1 = (0,stmt1,1) in
let ts = TransitionSets.add tr1 ts in
(vset,0,ts,10)
In the above code I am defining some types. Now if I include the command "open Z3", I am getting "Error: Unbound module Set.Make".
I could run test code which uses Z3 module with out any difficulty, but unable to run with the above code.
The error message in this case is a little bit confusing. The problem is that Z3 also provides a module called Set, which doesn't have a make function. This can be overcome simply by not importing everything from Z3, as there are a number of modulse that might clash with others. For example,
open Z3.Expr
open Z3.Boolean
will work fine and opens only the Z3.Expr and Z3.Boolean modules, but not the Z3.Set module. so that we can write an example function:
let myfun (ctx:Z3.context) (args:expr list) =
mk_and ctx args
If Z3.Boolean is not opened, we would have to write Z3.Boolean.mk_and instead, and similarly we can still access Z3's Set module functions by prefixing them with Z3.Set.