I have a struct Context that as a type takes an association list from string to a custom type process.
I'm trying to pattern match to see if my struct is empty (this seems to work fine) however checking whether my struct contains elements is giving me the following error.
File "src/main.ml", line 131, characters 13-30:
131 | | Context.((ext_ref,prc)::tl) ->
^^^^^^^^^^^^^^^^^
Error: This pattern matches values of type 'a list
but a pattern was expected which matches values of type t
Here is the code that won't compile:
(* Finds a recv corresponding to a send stmt *)
let rec find_recv (ctx: Context.t) (external_ref:variable) =
match ctx with
| Context.(empty) -> None
| Context.((ext_ref,prc)::tl) ->
begin
match prc with
| Prc(_, _,Recv(_,_,chn,_)) -> if chn = external_ref then Some prc else find_recv tl external_ref
|_ -> find_recv tl external_ref
end
Here is the signature for the 'Context' struct.
module type Context = sig
type t
val empty : t
val lookup : t -> string -> process
val extend : t->string ->process -> t
val filter : t->string ->t
end
Here is the instantiation of my Context module:
(** Instantiating a Process Table *)
module Context : Context = struct
type t = (string * process) list
let empty = []
let lookup (ctx:t) (x:string): process=
let chck = List.assoc_opt x ctx in match chck with
|Some i -> i
|None -> Null("")
let extend (ctx:t) (x:string) (ty:process) =
(x, ty) :: ctx
let filter ctx x =
List.remove_assoc x ctx
end
I got this code from the Real World Ocaml book.
Given the constraints of your Context signature, type t within the Context module is abstract.
Within the module, your functions know that empty is a list. However, outside of it, empty is merely of abstract type Context.t.
Let's look at a simpler example:
utop # module type S =
sig
type t
val empty : t
end
module M : S =
struct
type t = int list
let empty = []
end;;
module type S = sig type t val empty : t end
module M : S
utop # M.empty;;
- : M.t = <abstr>
utop # match M.empty with [] -> "hello" | _ -> "world";;
Error: This pattern matches values of type 'a list
but a pattern was expected which matches values of type M.t
M.t is abstract. We know it exists, but not how it is implemented. This abstraction is frequently useful in designing applications.
It is possible to break this abstraction. Whether it's a good idea is a matter of opinion and outside of Stack Overflow's scope.
utop # module M2 : S with type t = int list =
struct
type t = int list
let empty = []
end;;
module M2 : sig type t = int list val empty : t end
utop # match M2.empty with [] -> "hello" | _ -> "world";;
- : string = "hello"
As kindly pointed out by #glennsl and as is explained better than I can in this thread Unbound constructor error when using module signature
My problem can be solved by including the find_recv function within the Modules signature as below.
module type Context = sig
type t
val empty : t
val lookup : t -> string -> process
val extend : t->string ->process -> t
val filter : t->string ->t
val find_recv: t -> variable -> process option
end
Obviously this must then be instantiated before use.
Related
So I have a record type with mutable field:
type mpoint = { mutable x:int ; mutable y: int };;
let apoint = { x=3 ; y=4};;
And I have a function that expects a 'ref' and does something to its contents.
For example:
let increment x = x := !x+1;;
val increment : int ref -> unit = <fun>
Is there a way to get a 'reference' from a mutable field so that I can pass it to the function. I.e. I want to do something like:
increment apoint.x;; (* increment value of the x field 'in place' *)
Error: This expression has type int but an expression was expected of type
int ref
But the above doesn't work because apoint.x returns the value of the field not its 'ref'. If this was golang or C++ maybe we could use the & operator to indicate we want the address instead of the value of the field: &apoint.x.
(How) can we do this in Ocaml?
PS: Yes, I know its probably more common to avoid using side-effects in this way. But I promise, I am doing this for a good reason in a context where it makes more sense than this simplified/contrived example might suggest.
There's no way to do exactly what you ask for. The type of a reference is very specific:
# let x = ref 3
val x : int ref = {contents = 3}
A reference is a record with one mutable field named contents. You can't really fabricate this up from an arbitrary mutable field of some other record. Even if you are willing to lie to the type system, a field of a record is not represented at all the same as a record.
You could declare your fields as actual references:
type mpoint = { x: int ref; y: int ref; }
Then there is no problem, apoint.x really is a reference. But this representation is not as efficient, i.e., it takes more memory and there are more dereferences to access the values.
If an API is designed in an imperative style it will be difficult to use in OCaml. That's how I look at it anyway. Another way to say this is that ints are small. The interface should perhaps accept an int and return a new int, rather than accepting a reference to an int and modifying it in place.
Jeffrey Scofield explained why this can't be done in ocaml from the point of the type system.
But you can also look at it from the point of the GC (garbage collector). In ocaml internally everything is either a trivial type (int, bool, char, ...) that is stored as a 31/63 bit value or a pointer to a block of memory. Each block of memory has a header that describes the contents to the GC and has some extra bits used by GC.
When you look at a reference internally it is a pointer to the block of memory containing the record with a mutable contents. Through that pointger the GC can access the header and know the block of memory is still reachable.
But lets just assume you could pass apoint.y to a function taking a reference. Then internally the pointer would point to the middle of apoint and the GC would fail when it tries to access the header of that block because it has no idea at what offset to the pointer the header is located.
Now how to work around this?
One way that was already mentioned is to use references instead of mutable. Another way would be to use a getter and setter:
# type 'a mut = (unit -> 'a) * ('a -> unit);;
type 'a mut = (unit -> 'a) * ('a -> unit)
# type mpoint = { mutable x:int ; mutable y: int };;
type mpoint = { mutable x : int; mutable y : int; }
# let mut_x p = (fun () -> p.x), (fun x -> p.x <- x);;
val mut_x : mpoint -> (unit -> int) * (int -> unit) = <fun>
# let mut_y p = (fun () -> p.y), (fun y -> p.y <- y);;
val mut_y : mpoint -> (unit -> int) * (int -> unit) = <fun>
If you only want to incr the variable you can pass an incrementer function instead of getter/setter. Or any other collection of helper functions. A getter/setter pait is just the most generic interface.
You can always copy temporarily the content of field, call the function on that, and back again:
let increment_point_x apoint =
let x = ref apoint.x in
increment x;
apoint.x <- !x
Certainly not as efficient (nor elegant) as it could, but it works.
It is impossible to do exactly what the question asks for (#JeffreyScofield explains why, so I won't repeat that). Some workarounds have been suggested.
Here is another workaround that might work if you can change the implementation of the increment function to use a 'home made' ref type. This comes very close to what was asked for.
Instead of having it take a 'built-in' reference, we can define our own type of reference. The spirit of a 'reference' is something you can set and get. So we can characterise/represent it as a combination of a get and set function.
type 'a ref = {
set: 'a -> unit;
get: unit -> 'a;
};;
type 'a ref = { set : 'a -> unit; get : unit -> 'a; }
We can define the usual ! and := operators on this type:
let (!) cell = cell.get ();;
val ( ! ) : 'a ref -> 'a = <fun>
let (:=) cell = cell.set;;
val ( := ) : 'a ref -> 'a -> unit = <fun>
The increment function's code can remain the same even its type 'looks' the same (but it is subtly 'different' as it is now using our own kind of ref instead of built-in ref).
let increment cell = cell := !cell + 1;;
val increment : int ref -> unit = <fun>
When we want a reference to a field we can now make one. For example a function to make a reference to x:
let xref pt = {
set = (fun v -> pt.x <- v);
get = (fun () -> pt.x);
};;
val xref : mpoint -> int ref = <fun>
And now we can call increment on the x field:
increment (xref apoint);;
- : unit = ()
Suppose I have the following signatures:
sig A {}
sig B {}
sig P {
a: A,
b: B
}
How can I write a function f, say, such that f returns the set of P for which each member has the value x: A for its a field?
Entering the expression {p: P | p.a = x} into the evaluator gives me back a set, but when I try to define f in this manner
fun f(a: A) : set P {
{ p: P | p.a = a }
}
alloy tells me I've made an error:
A type error has occurred
This cannot be a legal relational join where
left hand side is p (type = {this/P})
right hand side is a (type = {this/A})
The problem is that you shadowed the a relation with your function parameter. It works if you replace f(a: A) with f(a': A). Alternatively, you can use the # operator, which returns the global instead of local value of a set:
fun f(a: A) : set P {
{ p: P | p.#a = a }
}
I would like to define a data type that is a record with one function named f:
data A = A { f :: Int -> Int }
and I would like to create an instance:
A {f x = x * 2 }
However: this gives a syntax error:
error: parse error on input ‘x’
The following is the grammar for constructions using field labels.
aexp → qcon { fbind1 , … , fbindn } (labeled construction, n ≥ 0)
fbind → qvar = exp
Note that qcon is a constructor syntax, qvar is a variable syntax, and exp is an expression syntax.
The reason A {f x = x * 2} does not work therefore is because it is invalid syntax. A syntax that is valid and that is probably what you want is A {f = \x -> x * 2}. Alternatively, A {f = (* 2)}, A {f = (2 *)}, or A {f = (*) 2}.
Construction using field labels operates like named parameters. Given a data type definition such as
data Person = Person { name :: String, age :: Int }
The expression
Person { age = 65, name = "Wilbur Suidae" }
Means
Person "Wilbur Suidae" 65
That is, the constructor arguments are ordered to match the order of fields according to the constructor definition.
The expression
Person { age = 65 }
Means
Person undefined 65
That is, if a field is not explicitly assigned a value it is implicitly assigned the value undefined.
References
Construction Using Field Labels, § 3.15.2, Haskell Report 2010
I'm looking for a way to simplify function patterns when the actual data is not required:
data X = A | B String | C Int Int String
myfn :: X -> Int
myfn A = 50
myfn (B _) = 200
myfn (C _ _ _) = 500
Is there a way to make a simpler pattern for matching C, just discarding the values?
hsdev adds a hint "Hint: use record patterns", but Google did not help me there.
You can use record patterns like this:
data X = A | B {name :: String} | C {x::Int, y::Int, name::String}
myfn :: X -> Int
myfn A = 50
myfn B{} = 200
myfn C{} = 500
Record patterns allow you to give names to the fields of the constructors.
you can also do things like:
myfn C{name=n} = length n
so you can see that you can pattern match only on the specific field you need.
Note: you can use the empty record pattern even with data types that do not use record syntax:
data A = A Int | B Int Int
myfn A{} = 1
myfn B{} = 2
This is fine.
There a number of other extensions related to record patterns:
RecordWildCards allows you to write things like C{..} which is equivalent to the pattern: C{x=x, y=y, name=name}, i.e. it matches all fields and you now have in scope x with the value matched for the x field etc.
NamedFieldPuns allows you to write C{name} to be equivalent to C{name=name}, so that name is now in scope and contains the value matched for the name field.
Keep in mind that using record patterns doesn't prevent you from using your constructors in a positional way, so you can still write:
myfn (B _) = 200
It only adds functionality.
I wanted this kind of expression in OCaml
let wrapper obj f = fun raw -> f (new obj raw)
But I get a compiler error of Unbound class obj but so what, why isn't the compiler satisfied with creating this function which just says call a function on this object which happens to take one init arg.
Pass a function that constructs the object. For a one-argument class foo you can use new foo to get that function.
let wrapper make_obj f raw = f (make_obj raw)
class foo (x) = object
method y = x + 1
end
let answer = wrapper (new foo) (fun o -> o#y) 2
Here, wrapper has a very general type that doesn't mention objects at all. If you want to make it clear that an object constructor is expected as the argument, you can restrict the type with an annotation:
let wrapper (make_obj: (_ -> < .. >)) f raw = f (make_obj raw)
One way to look at this is that an OCaml class is a type, not a value. So you can't write a function in OCaml that accepts a class as a parameter.
Here's a session:
$ ocaml
OCaml version 4.02.1
# class abc = object method m = 12 end;;
class abc : object method m : int end
# abc;;
Error: Unbound value abc
# let f (x: abc) = x#m ;;
val f : abc -> int = <fun>
# f (new abc);;
- : int = 12
As you can see, abc is a type. Not a value.
In other languages, classes are values. But not in OCaml.