Outputting strings into a file from Isabelle/HOL - isabelle

I would like to output strings into a file from an Isabelle/HOL theory.
The solution that I came up with involves doing file and string manipulation at the level of ML.
For example, let's suppose the following Isabele/HOL code that defines the abstract syntax of a very simple expression language:
datatype Exp = expid string
| exppar Exp
| expplus Exp Exp
| expminus Exp Exp
| expnum int
I would like to output the pretty-printing of expressions of this simple language into a file. For example, an expression such as:
definition exp_exmp :: "Exp"
where
"exp_exmp ≡ expplus
(exppar (expminus (expnum 2) (expid ''x'')))
(exppar (expplus (expid ''y'') (expnum 5)))"
I managed to do this at the ML level by using the code generation features of Isabele/HOL:
export_code exp_exmp expid str_int in SML module_name Example file "example.sml"
To facilitate things with string manipulation, I have defined the pretty print function in ML. So I end up with the code:
ML_file "example.sml"
ML {*
open Example;
fun charsToStr [] = ""
| charsToStr (c::cs) = (str c)^charsToStr cs
fun wrExp (Expid i) = charsToStr i
| wrExp (Exppar e) = "(" ^ wrExp e ^ ")"
| wrExp (Expnum n) = charsToStr (str_int n)
| wrExp (Expplus (e1, e2)) =
wrExp e1 ^"+"^wrExp e2
| wrExp (Expminus (e1, e2)) =
wrExp e1 ^ "-" ^ wrExp e2
val file = TextIO.openOut("exmp.txt");
TextIO.output (file, wrExp exp_exmp);
TextIO.closeOut(file);
*}
In doing this, importing the theory "~~/src/HOL/Library/Code_Char" was crucial to ease the necessary conversions between the Isabelle/HOL representations of chars and string and those of ML.
Is this the best way of doing it?

Related

Errors while iterating and processing the split string in recursive functions

Let's say we have a string
"+x1 +x2 -x3
+x4 +x5 -x6
..."
and a type formula:
type formula =
| Bot
| Top
| Atom of string
| Imp of (formula * formula)
| Or of (formula * formula)
| And of (formula * formula)
| Not of formula
let atom x = Atom x
(aka predicate logic)
and we want to:
Create a function which takes one line, splits it and turns it into disjunction using the formula type. (sort of like Or(Atom "x1", Atom "x2", Not Atom "x3") if we give the first line as an input)
I've written this:
let string_to_disj st =
let lst = Str.split (Str.regexp " \t") st in
let rec total lst =
match lst with
| [] -> Or (Bot, Bot) (*Is this correct btw?*)
| h :: t -> Or (string_to_lit h, total t);;
where
let string_to_lit =
match String.get s 0 with
| '+' -> atom (String.sub s 1 (String.length s-1))
| '-' -> Not(atom(String.sub s 1 (String.length s-1)))
| _ -> atom(s);;
However, string_to_disj raises a syntax error at line
| h :: t -> Or (string_to_lit h, total t)
What have I done wrong?
You have let rec total lst but you have no matching in. Every let requires a matching in. (Except at the top level of a module where it is for defining exported symbols of the module).
Also note that you are defining a function named total but you have no calls to the function except the one recursive call.

How can I write a function to evaluate custom datatype

datatype mixed_expression =
ME_NUM of int
| ME_PLUS of mixed_expression * mixed_expression
| ME_TIMES of mixed_expression * mixed_expression
| ME_LESSTHAN of mixed_expression * mixed_expression;
datatype value =
INT_VAL of int
| BOOL_VAL of bool
| ERROR_VAL;
I am given these data types and this is my approach
fun eval e =
case e of
ME_NUM x => INT_VAL x
| ME_PLUS (l, r) => eval l + eval r
I got the following error message.
**Error: overloaded variable not defined at type
symbol: +
type: value**
I have no clues on how to solve these issues since I am not allowed to use mutation.
The error message tells you what you need to know. When you write:
eval l + eval r
The expressions eval l and eval r yield type value. There is no + operator for this type.
As a style note, your case is extraneous in this situation.
fun eval(ME_NUM x) = INT_VAL x
| eval(ME_PLUS (l, r)) = eval l + eval r
You should also get a warning about pattern-matching being non-exhaustive as you haven't handled ME_TIMES or ME_LESSTHAN.
Really, what you need to do is define a function which can add two value values.
fun me_add(INT_VAL a, INT_VAL b) = INT_VAL (a + b)
| me_add(INT_VAL a, BOOL_VAL b) = (* ... *)
There are lots of combinations you'll need to pattern-match on. You may want to just define a function that coerces a value into an int.
fun toInt(INT_VAL a) = a
| toInt(BOOL_VAL True) = 1
| toInt(BOOL_VAL False) = 0
| (* and so on... *)
Then you could write something like:
fun me_add(a, b) = INT_VAL(toInt a + toInt b)
The problem is that there is no + operator defined for the value type.
(You would not solve this by using mutation.)
You need to "pick apart" the results of eval and then build a new value from the addition.
The most naive approach would be a case analysis, but this gets unreadable very quickly:
eval (ME_PLUS (e1, e2)) = (case eval e1 of
INT_VAL x1 => (case eval e2 of
INT_VAL x2 => INT_VAL (x1 + x2)
| _ => ERROR_VAL)
| _ => ERROR_VAL)
and you would need one of these uglinesses for each case.
A tidier approach is to define the operations on values as separate functions:
fun add (INT_VAL x1) (INT_VAL x2) = INT_VAL (x1 + x2)
| add _ _ = ERROR_VAL;
and so on.
Then you define your interpreter in terms of these operations:
fun eval (ME_NUM x) = INT_VAL x
| eval (ME_PLUS (e1, e2)) = add (eval e1) (eval e2)
| eval (ME_TIMES (e1, e2)) = multiply (eval e1) (eval e2)
| eval (ME_LESSTHAN (e1, e2)) = less_than (eval e1) (eval e2);

Implementing type equation generator in OCaml

type exp =
| CONST of int
| VAR of var
| ADD of exp * exp
| SUB of exp * exp
| ISZERO of exp
| IF of exp * exp * exp
| LET of var * exp * exp
| PROC of var * exp
| CALL of exp * exp
and var = string
type typ = TyInt | TyBool | TyFun of typ * typ | TyVar of tyvar
and tyvar = string
type typ_eqn = (typ * typ) list
module TEnv = struct
type t = var -> typ
let empty = fun _ -> raise (Failure "Type Env is empty")
let extend (x,t) tenv = fun y -> if x = y then t else (tenv y)
let find tenv x = tenv x
end
let rec gen_equations : TEnv.t -> exp -> typ -> typ_eqn
=fun tenv e ty -> match e with
| CONST n -> [(ty, TyInt)]
| VAR x -> [(ty, TEnv.find tenv x)]
| ADD (e1,e2) -> [(ty, TyInt)]#
[gen_equations (tenv, e1, TyInt)]#
[gen_equations (tenv, e2, TyInt)]
Hi, I'm trying to implement the type equation generator that I recently learned in class.
But when I tried implementing the ADD expression using the above method, I get an error saying, "This expression has type ('a -> 'b -> typ_eqn) list, but an expression was expected of type (typ * typ) list."
Isn't appending two or more typ_eqn type lists basically the same thing as (typ * typ) list?
edit:
let rec gen_equations : TEnv.t -> exp -> typ -> typ_eqn
=fun tenv e ty -> match e with
| CONST n -> [(ty, TyInt)]
| VAR x -> [(ty, TEnv.find tenv x)]
| ADD (e1,e2) -> let l1 = [(ty, TyInt)] in
let l2 = gen_equations (tenv, e1, TyInt) in
let l3 = gen_equations (tenv, e2, TyInt) in
l1::l2::l3
I've tried this method too, but this gives me an error message:
"This expression has type (typ * typ) list, but an expression was expected of type (typ * typ)."
Why is this suddenly expecting something different???
In your first version you write [gen_equations (tenv, e1, TyInt)], but gen_equations already returns a list. You might try writing just gen_equations tenv e1 TyInt (note change from uncurried to curried form).
In your second version, you're using :: to join two lists. But :: is for joining an element to a list. You might try l1 # l2 # l3.
Update
In both versions, you're calling gen_equations in uncurried form, but it is defined in curried form. Call like this: gen_equations tenv e1 TyInt.

Printing a list of lists in OCaml

So I am trying to print a list of lists that would look like this:
[0;0;0;0;0];
[0;0;0;0;0];
[0;0;1;0;0];
[0;0;0;0;0];
I can use as many functions as necessary, but only one function may use a print function. Here is what I have so far:
let rec rowToString(row) =
if (row == []) then []
else string_of_int(List.hd row) :: ";" :: rowToString(List.tl row);;
let rec pp_my_image s =
print_list(rowToString(List.hd s)) :: pp_my_image(List.tl s);;
I know this is wrong, but I can't figure out a way to do it.
Here is one way to do it:
let rec rowToString r =
match r with
| [] -> ""
| h :: [] -> string_of_int h
| h :: t -> string_of_int h ^ ";" ^ (rowToString t)
let rec imageToString i =
match i with
| [] -> ""
| h :: t -> "[" ^ (rowToString h) ^ "];\n" ^ (imageToString t)
let pp_my_image s =
print_string (imageToString s)
The rowToString function will create a string with the items in each inner list. Notice that case h :: [] is separated so that a semicolon is not added after the last item.
The imageToString function will create a string for each inner list with a call to rowToString. It will surround the result of each string with brackets and add a semicolon and newline to the end.
pp_my_image will simply convert the image to a string and print the result.

Default recursion on recursive types

Idiomatic F# can nicely represent the classic recursive expression data structure:
type Expression =
| Number of int
| Add of Expression * Expression
| Multiply of Expression * Expression
| Variable of string
together with recursive functions thereon:
let rec simplify_add (exp: Expression): Expression =
match exp with
| Add (x, Number 0) -> x
| Add (Number 0, x) -> x
| _ -> exp
... oops, that doesn't work as written; simplify_add needs to recur into subexpressions. In this toy example that's easy enough to do, only a couple of extra lines of code, but in a real program there would be dozens of expression types; one would prefer to avoid adding dozens of lines of boilerplate to every function that operates on expressions.
Is there any way to express 'by default, recur on subexpressions'? Something like:
let rec simplify_add (exp: Expression): Expression =
match exp with
| Add (x, Number 0) -> x
| Add (Number 0, x) -> x
| _ -> recur simplify_add exp
where recur might perhaps be some sort of higher-order function that uses reflection to look up the type definition or somesuch?
Unfortunately, F# does not give you any recursive function for processing your data type "for free". You could probably generate one using reflection - this would be valid if you have a lot of recursive types, but it might not be worth it in normal situations.
There are various patterns that you can use to hide the repetition though. One that I find particularly nice is based on the ExprShape module from standard F# libraries. The idea is to define an active pattern that gives you a view of your type as either leaf (with no nested sub-expressions) or node (with a list of sub-expressions):
type ShapeInfo = Shape of Expression
// View expression as a node or leaf. The 'Shape' just stores
// the original expression to keep its original structure
let (|Leaf|Node|) e =
match e with
| Number n -> Leaf(Shape e)
| Add(e1, e2) -> Node(Shape e, [e1; e2])
| Multiply(e1, e2) -> Node(Shape e, [e1; e2])
| Variable s -> Leaf(Shape e)
// Reconstruct an expression from shape, using new list
// of sub-expressions in the node case.
let FromLeaf(Shape e) = e
let FromNode(Shape e, args) =
match e, args with
| Add(_, _), [e1; e2] -> Add(e1, e2)
| Multiply(_, _), [e1; e2] -> Multiply(e1, e2)
| _ -> failwith "Wrong format"
This is some boilerplate code that you'd have to write. But the nice thing is that we can now write the recursive simplifyAdd function using just your special cases and two additional patterns for leaf and node:
let rec simplifyAdd exp =
match exp with
// Special cases for this particular function
| Add (x, Number 0) -> x
| Add (Number 0, x) -> x
// This now captures all other recursive/leaf cases
| Node (n, exps) -> FromNode(n, List.map simplifyAdd exps)
| Leaf _ -> exp

Resources