Is there a way to obtain a 'reference' to a mutable struct field - reference

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 = ()

Related

Structures and Pattern Matching

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.

Use where outside the Haskell function

I'm wondering whether we can use where outside a function?
e.g.
fun::Int->Int
fun n = n + 1
main = do
fun x where x = 30
Obviously it does't work when I compile it,
I want to declare x as local variable for fun only
Your function has the wrong type to be used as the final expression in a do block. It needs to return an Monad m => m Int value, not simply an Int. As main (in its usual use) is required to be an IO action, this means m should be IO.
fun :: Int -> IO Int
fun n = return (n + 1)
A let would be more appropriate than a where in this case, though.
main = do
let x = 30 in fun x
Now, x is in scope only for the call to fun. If you wrote
main = do
let x = 30
fun x
then x is technically in scope for the rest of the do block, not just the call to fun. Despite sharing the same keyword let, there is a distinct difference between a let in a do block and a regular let expression. (The relationship is that
do
let name = value
foo
is equivalent to
let name = value
in do
foo
)
Note that do itself does not create a monadic value; it is simply syntactic sugar for various operators which assume monadic properties. A quick overview:
do { x <- y; foo x; } becomes y >>= (\x -> foo x).
do { foo; bar; } becomes foo >> bar.
do { let x = y; foo; } becomes let x = y in do foo
do foo becomes foo.
Most relevant to your code is rule 4; a single expression in a do block is equivalent to the expression by itself, meaning you can strip the do. Only after the do block is desugared does Haskell begin to type-check the result.

Constructing Poly/ML parametric struct value

I want to create a struct which is based on another struct whose implementation can be switched.
signature Field =
sig
type field_type;
val zero : field_type;
val add : (field_type * field_type) -> field_type;
val f : int -> field_type;
end;
structure Reals :> Field =
struct
type field_type = real;
val zero = 0.0;
fun add (x,y) = x + y;
fun f x = Real.fromInt(x);
end;
structure Rat :> Field =
struct
type field_type = int * int;
val zero = (0, 1);
fun add ((i1,i2),(j1,j2)) = (i1*j2 + j1*i2, i2*j2);
fun f x = (x, 1);
end;
functor Useable(F : Field) =
struct
type field_type = F.field_type;
val zero = F.zero;
fun add(x,y) = F.add(x,y);
fun f x = F.f x;
end;
structure ReF = Useable(Reals);
structure RaF = Useable(Rat);
The idea is that I could plug in implementations of Field (Reals or Rat, ignore the inefficient implementations).
I can run this code ReF.add(ReF.zero, ReF,zero), but can't run ReF.add(0.0, 0.0) (or RaF.add((0,1),(0,1)))
To overcome this I created a constructor f: int -> field_types, but I found this to be not so elegant and also cumbersome. Can I do anything for being able to use ReF.add(0.0, 0.0)?
The simple answer is to use a transparent signature constraint
structure Reals : Field
rather than an opaque constraint.
structure Reals :> Field
When you use an opaque constraint types such as field_type in the signature are created as new types distinct from the types that are used to implement them. If you want to retain the link to the original type you need to use a transparent constraint. With a transparent constraint Reals.field_type and real are the same type so you can use
ReF.add(0.0, 0.0);
perfectly well.
> ReF.add(0.0, 0.0);
val it = 0.0: real
As an alternative to using a transparent constraint, if you have other types in your signature that you want to be created as new types, you can still get the desired effect by using an opaque constraint along with where type.
structure Reals :> Field where type field_type = real

(OCaml) Strange syntax used in queue.ml -- The `<-` operator

While browsing the Caml Light library for programming examples, I stumbled across the following code, taken from the Caml Light queue.ml file:
type 'a queue_cell =
Nil
| Cons of 'a * 'a queue_cell ref
;;
type 'a t =
{ mutable head: 'a queue_cell;
mutable tail: 'a queue_cell }
;;
let add x = function
{ head = h; tail = Nil as t } -> (* if tail = Nil then head = Nil *)
let c = Cons(x, ref Nil) in
h <- c; t <- c
| { tail = Cons(_, ref newtail) as oldtail } ->
let c = Cons(x, ref Nil) in
newtail <- c; oldtail <- c
;;
This implementation of FIFO data structures puzzles me. I get the general idea, to keep a pointer to the last entry in the structure, so that appending at the end is possible. This makes perfect sense to me. However, it's the syntax of how this is done that bugs me.
Consider the following:
| { tail = Cons(_, ref newtail) as oldtail } ->
let c = Cons(x, ref Nil) in
newtail <- c; oldtail <- c
I have a problem with types here. By the type definition, newtail should be of type 'a queue cell, since it's retrieved using Cons(_, ref newtail) in the pattern matching: if I understand correctly, this would mean that newtail binds the value pointed by the second member of the tail record field (which originally is a reference).
So what does the newtail <- c means? If I try to replace this statement by (fun x -> x <- c) newtail, I get The identifier x is not mutable., whereas the code sounds perfectly similar to the original variant to me.
Would rewriting these few lines to read as follows mean the same?
| { tail = Cons(_, newtail) as oldtail } ->
let c = Cons(x, ref Nil) in
newtail := c; oldtail <- c
Taking the question one step further, what does the following code actually do?
type t = Nil | Node of (t ref);;
type box = {mutable field: t};;
let poke = function
| {field = Node(ref n)} -> n <- Nil
| {field = Nil} -> ()
;;
let test = {field = Node(ref (Node(ref Nil)))};;
poke test;;
test;;
Is it the same to write
{field = Node(n)} -> n := Nil
and
{field = Node(ref n)} -> n <- Nil
?
Even stranger: the following code returns The value identifier a is unbound.
let a = Nil;;
a <- Nil;; (* The value identifier a is unbound. *)
Could someone take the time to clarify the use of <- for me? The various examples here are pretty puzzling to me...
Thanks!
EDIT: This was originally posted to the Caml Mailing list, but I thought the post didn't make it, so I posted it here. It appears that the posting did work; sorry for that: the link to the mailing list answer (which its original author also posted here), is https://sympa-roc.inria.fr/wws/arc/caml-list/2011-01/msg00190.html.
See my answer on the caml list
Why ask the same question twice in different places ? This only leads to a duplication of efforts, with knowledgeable people wasting their time to answer you.
If you want to do that, please at least post cross-references (from your stackoverflow post to the list archive, and vice versa[1]), so that people can check that it hasn't been answered yet in the other place.
[1] yes, you can have cyclic cross-references, as the stackoverflow post is mutable!
The semantics of mutable fields and references has changed a lot (for good)
between Caml Light and Objective Caml. Beware that this code is Caml Light
specific -- and if you want to learn Caml, you should rather be using
Objective Caml, which is the implementation that is still maintained.
In Objective Caml, only records fields are mutable. References are a derived
concept, the type 'a ref is defined as :
type 'a ref = { mutable contents : 'a }
You change a mutable field with the syntax foo.bar <- baz (where "bar" is
a record field, and foo and baz are any expression, foo being of a record
type)
In Caml Light, record fields are mutable, but sum type fields (variants) are
mutable as well; mutable variant fields are however not used here. See
http://caml.inria.fr/pub/docs/manual-caml-light/node4.6.html for
documentation.
In Caml Light, a record may return a mutable location, akin to a lvalue in
C-like languages. For example, with the mutable variant
type foo = Foo of mutable int
you may write:
let set_foo (f : foo) (n : int) =
match f with
| Foo loc ->
loc <- n
"foo <- bar" is used here to assign a value "bar" to a lvalue "foo" bound in
a mutable pattern.
In your example, two mutable patterns are used :
| { tail = Cons(_, ref newtail) as oldtail } ->
oldtail is a mutable pattern denoting the mutable "tail" field of the
record
(ref newtail) is a specific syntax, a pattern on references. It binds a
mutable pattern "newtail" corresponding to the location of the reference
In other words, in Caml Light you can write the ":=" operator as such:
let prefix := r v =
match r with
| ref loc ->
loc <- v
Hope that helps.
.
Edit:
About the strange error message: I think that internally, Caml Light maintain a list of "value identifiers" in the scope, which come from pattern matching a mutable field (record or variant). When they see a foo <- bar expression, they look in that environment to find the corresponding location. Such environment is local to the expression, it never escapes. In particular at toplevel it is empty, and the errors tells you that no "value identifier" (mutable pattern) exists in the scope.
There is another thing: the namespace of value identifiers and usual identifiers are not distinct. When you match a value identifier, Caml Light adds to the scope the value identifier (mutable), but also the corresponding identifier with the matched rvalue. This can be quite confusing as you may mutate the location, but the value won't change :
#match ref 1 with (ref x) -> (x <- 2; x);;
- : int = 1
#match ref 1 with (ref x) as a -> (x <- 2; !a);;
- : int = 2
The (value) identifier will shadow any older identifier (value identifier or not)
#let x = 1 in let (ref x) = ref 2 in x;;
- : int = 2
(If you didn't know, let pattern = e1 in e2 is equivalent to match e1 with pattern -> e2 (except for the type system))
As the syntaxic classes for identifiers and value identifiers are the same, a non-mutable identifier will also shadow a value identifier, giving birth to a different error:
#let (ref x) = ref 2 in let x = 1 in x <- 3;;
Toplevel input:
>let (ref x) = ref 2 in let x = 1 in x <- 3;;
> ^^^^^^
The identifier x is not mutable.
In OCaml, the <- operator mutates mutable fields or object instance variables (references are mutated with :=). However, there are other things going on like the ref in your pattern matching that are unfamiliar to me. I think that it is signalling to Caml Light to match the cell as a reference (analogous to lazy in pattern matches in OCaml), resulting in a variable that is viable as the left-hand side of <- for mutation. Passing the variable into the function passes the value of the variable, which is not mutable, and therefore the function cannot mutate it.
So: it looks like matching the new tail as ref newtail establishes newtail as a sugared name such that evaluating newtail is transformed to !newtail' (where newtail' is some internal name representing the reference itself) and newtail <- foo transforms to newtail' := foo.
I don't actually know Caml Light, though, and I am unfamiliar with this sugaring if it even exists in OCaml (the code you provided does not compile in OCaml) but that's what it looks like is happening to me.

Is there a programming language that performs currying when named parameters are omitted?

Many functional programming languages have support for curried parameters.
To support currying functions the parameters to the function are essentially a tuple where the last parameter can be omitted making a new function requiring a smaller tuple.
I'm thinking of designing a language that always uses records (aka named parameters) for function parameters.
Thus simple math functions in my make believe language would be:
add { left : num, right : num } = ...
minus { left : num, right : num } = ..
You can pass in any record to those functions so long as they have those two named parameters (they can have more just "left" and "right").
If they have only one of the named parameter it creates a new function:
minus5 :: { left : num } -> num
minus5 = minus { right : 5 }
I borrow some of haskell's notation for above.
Has any one seen a language that does this?
OCaml has named parameters and currying is automatic (though sometimes type annotation is required when dealing with optional parameters), but they are not tupled :
Objective Caml version 3.11.2
# let f ~x ~y = x + y;;
val f : x:int -> y:int -> int = <fun>
# f ~y:5;;
- : x:int -> int = <fun>
# let g = f ~y:5;;
val g : x:int -> int = <fun>
# g ~x:3;;
- : int = 8
Sure, Mathematica can do that sort of thing.

Resources