In case I have to disassemble a data type as its variable size, can I still use the "match and with, and if the answer is yes you could help me figure out how (I'm a beginner with this language), or do I or use other methods.
the type defined is this :
type 'state formula =
| And of 'state formula list
| Or of 'state formula list
| Literal of bool
| Variable of 'state
from the examples I've seen the "match and with" is used when the structure of the static type was, in my case as I do?
So here's an example which uses match to work with your formula type:
type 'state formula = | And of 'state formula list | Or of 'state formula list | Literal of bool | Variable of 'state
let rec count_vars form = match form with
| And forms
| Or forms -> List.fold_left (+) 0 (List.map count_vars forms)
| Literal _ -> 0
| Variable _ -> 1
let formula = And [ Variable "q0"; Or[ Variable "q1";Variable "q2"]; Variable "q3"]
let vars_in_formula = count_vars formula (* 4 *)
If you want to manipulate the type, you can use patter matching(among other things, but I find this the most elegant). It's essentially syntactical sugar for Match with.
For example:
let identify_formula=function
And(l) -> 0
|Or(l) -> 1
|Literal(b) -> 2
| Variable(v) -> 3;;
For a less trivial example of how to manipulate types:
type l=Cons of int*l
| Nil;;
let rec sum_l=function
Cons(hd,tl)->hd+ sum_l(tl)
| Nil-> 0;;
sum_l(Cons(1,Cons(2,Cons(3,Nil))));; (*r6*)
Maybe you would like a code example to adapt to your needs.
type 'state formula =
| Literal of bool
| And of 'state formula list
| Or of 'state formula list
| Variable of 'state
let rec eval variable_env formula =
match formula with
| Literal b -> b
| Variable v -> variable_env v
| And formulas -> List.for_all (eval variable_env) formulas
| Or formulas -> List.exists (eval variable_env) formulas
(* same as eval, different code *)
let rec eval2 env = function
| Literal b -> b
| Variable v -> env v
| And [] -> true
| And (hd::tl) -> eval env hd && eval2 env (And tl)
| Or [] -> false
| Or (hd::tl) -> eval env hd || eval2 env (Or tl)
Related
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.
I have a problem with how nested functions should be implemented in OCaml, i need the output (list) of one function to be the input of another. And both should be recursive. The problem is i've played around with the parameters and they arent feeding properly:
let toComb sentence =
let rec listCleanup sentence =
match sentence with
| [] -> []
| h::t when h = "" -> listCleanup t
| h::t -> h::listCleanup t
in
let rec toString listCleanup sentence =
match listCleanup sentence with
| [] -> ""
| [element] -> element
| h::t -> h ^ " " ^ toString listCleanup sentence
in
toString listCleanup sentence;;
If I use the function and its parameter as a parameter, there's a stack overflow, but if I use just the function without a parameter, I get a mismatch of parameters. What should be the fix here?
To correct your code, here is what would work properly:
let to_comb sentence =
let rec cleanup s = match s with
| [] -> []
| ""::tail -> cleanup tail
| hd::tail -> hd::cleanup tail in
let rec to_string s = match s with
| [] -> ""
| [x] -> x
| hd::tail -> hd ^ " " ^ to_string tail in
to_string (cleanup s)
Note that I only call cleanup once, because you only ever need to clean the whole sequence only once. However, turns out both of these function can be expressed more simply with predefined OCaml function:
let to_comb sentence =
sentence
|> List.filter (fun s -> s <> "")
|> String.concat " "
You could almost read this code out loud to get a description of what it does. It starts with a sentence, filters the empty words in it, then concatenates them with spaces in between.
open System
open System.Collections.Generic
type Node<'a>(expr:'a, symbol:int) =
member x.Expression = expr
member x.Symbol = symbol
override x.GetHashCode() = symbol
override x.Equals(y) =
match y with
| :? Node<'a> as y -> symbol = y.Symbol
| _ -> failwith "Invalid equality for Node."
interface IComparable with
member x.CompareTo(y) =
match y with
| :? Node<'a> as y -> compare symbol y.Symbol
| _ -> failwith "Invalid comparison for Node."
type Ty =
| Int
| String
| Tuple of Ty list
| Rec of Node<Ty>
| Union of Ty list
type NodeDict<'a> = Dictionary<'a,Node<'a>>
let get_nodify_tag =
let mutable i = 0
fun () -> i <- i+1; i
let nodify (dict: NodeDict<_>) x =
match dict.TryGetValue x with
| true, x -> x
| false, _ ->
let x' = Node(x,get_nodify_tag())
dict.[x] <- x'
x'
let d = Dictionary(HashIdentity.Structural)
let nodify_ty x = nodify d x
let rec int_string_stream =
Union
[
Tuple [Int; Rec (nodify_ty (int_string_stream))]
Tuple [String; Rec (nodify_ty (int_string_stream))]
]
In the above example, the int_string_stream gives a type error, but it neatly illustrates what I want to do. Of course, I want both sides to get tagged with the same symbol in nodify_ty. When I tried changing the Rec type to Node<Lazy<Ty>> I've found that it does not compare them correctly and each sides gets a new symbol which is useless to me.
I am working on a language, and the way I've dealt with storing recursive types up to now is by mapping Rec to an int and then substituting that with the related Ty in a dictionary whenever I need it. Currently, I am in the process of cleaning up the language, and would like to have the Rec case be Node<Ty> rather than an int.
At this point though, I am not sure what else could I try here. Could this be done somehow?
I think you will need to add some form of explicit "delay" to the discriminated union that represents your types. Without an explicit delay, you'll always end up fully evaluating the types and so there is no potential for closing the loop.
Something like this seems to work:
type Ty =
| Int
| String
| Tuple of Ty list
| Rec of Node<Ty>
| Union of Ty list
| Delayed of Lazy<Ty>
// (rest is as before)
let rec int_string_stream = Delayed(Lazy.Create(fun () ->
Union
[
Tuple [Int; Rec (nodify_ty (int_string_stream))]
Tuple [String; Rec (nodify_ty (int_string_stream))]
]))
This will mean that when you pattern match on Ty, you'll always need to check for Delayed, evaluate the lazy value and then pattern match again, but that's probably doable!
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
How can I re-write this function in OCaml so that it allows the elements of the tuple to have different types
let nth i (x,y,z) =
match i with
1->x
|2->y
|3->z
|_->raise (Invalid_argument "nth")
The short answer is that it's not possible. OCaml is strongly and statically typed. A function returns a single type. Since your function returns x, y, and z in different cases, then these must all be the same type.
OCaml types are not like types in the so-called dynamically typed languages. You need to think differently. The benefits are (in my opinion) tremendous.
It can be done, but you need to fulfill the constraint that all values, returned from the function should be members of one type. The easiest solution is:
let nth i (x,y,z) =
match i with
| 1 -> `Fst x
| 2 -> `Snd y
| 3 -> `Thd z
| _ -> invalid_arg "nth tuple"
The solution demonstrates that you need to address all possible cases for the types of your tuple. Otherwise, your program will not be well-formed, and this contradicts with the static typing. The latter guarantees that your program is well-formed for any input, so that it wont fail in a runtime.
A twin solution, using ordinary ADT instead of polymorphic ones, will look something like this:
type ('a,'b,'c) t =
| Fst of 'a
| Snd of 'b
| Thd of 'c
let nth i (x,y,z) =
match i with
| 1 -> Fst x
| 2 -> Snd y
| 3 -> Thd z
| _ -> invalid_arg "nth tuple"
An exotic solution (not very practible, maybe) that uses GADT to form an existential type will look like this:
type t = Dyn : 'a -> t
let nth i (x,y,z) =
match i with
| 1 -> Dyn x
| 2 -> Dyn y
| 3 -> Dyn z
| _ -> invalid_arg "nth tuple"