The one subject in SML which does not get much attention is 'records'.
I was wondering how to handle records in functions (as an argument or returented value). I know we can use the # operator in order to get an element of the record. But How should I pass the record to the function? is there a special pattern matching for that?
I have tried:
fun foo r = #1 r;
It ends with the following error:
Error: unresolved flex record
(can't tell what fields there are besides #1)
I didn't find any guide online which explains this part of records, in SML.
Also I tried:
fun foo {1=2,2=3} = 5;
And found out that tuples are actually syntax-sugar of records. Of Course I got the match warning, but at least it worked this time. The real question is how to handle 'generic' records. Could be helpful to see some examples or a reference to a guide on the subject.
It will be more then helpful to see also explanation about the signatures of those functions (as I mentioned records like {1=2,2=3} will get different signatures then {a=2,b=3}).
The one subject in SML which does not get much attention is 'records'.
I'm not sure what you mean. Standard textbooks on SML usually cover this. For example, ML for the Working Programmer, 2nd Ed. chapter 2, Names, Functions and Types, pp. 28 and on covers them. This book is free as a PDF, so you can read this chapter if you like.
If you read chapter 2, p. 34 it covers record patterns:
- val richardIII =
{ name = "Richard III"
, born = 1452
, crowned = 1483
, died = 1485
, quote = "Plots have I laid..."
};
> val richardIII =
{born = 1452, crowned = 1483, died = 1485, name = "Richard III",
quote = "Plots have I laid..."} :
{born : int, crowned : int, died : int, name : string, quote : string}
- val { name = richard_name, died = richard_died, ... } = richardIII;
> val richard_name = "Richard III" : string
val richard_died = 1485 : int
These record patterns are also possible in function arguments.
I recommend that you read a textbook on SML on this and other subjects.
StackOverflow is a poor format for reproducing one.
The real question is how to handle 'generic' records
Depending on what you mean by generic records, SML may not be able to do that.
For example, you can define the function
- fun f { x, y } = x + y;
> val f = fn : {x : int, y : int} -> int
But if you try to define one that extracts x and y from an arbitrary record without specifying the remaining record type,
- fun f { x, y, ... } = x + y;
! Toplevel input:
! fun f { x, y, ... } = x + y;
! ^^^^^^^^^^^^^
! Unresolved record pattern
Whereas if you specified the type of record,
- fun f ({ x, y, ... } : { x : int, y : int, z : int }) = x + y;
> val f = fn : {x : int, y : int, z : int} -> int
or equivalently via a type alias,
- type coord = { x : int, y : int, z : int };
> type coord = {x : int, y : int, z : int}
- fun f ({ x, y, ... } : coord) = x + y;
> val f = fn : {x : int, y : int, z : int} -> int
then that works as fine as using #x and #y:
- fun f (coord : coord) = #x coord + #y coord;
> val f = fn : {x : int, y : int, z : int} -> int
and without any kind of type annotation or inference, this will also fail to recognize the particular record type:
- fun f coord = #x coord + #y coord;
! Toplevel input:
! fun f coord = #x coord + #y coord;
! ^^
! Unresolved record pattern
So SML does not handle generic records in this sense even though it's technically possible to allow for this in a language. Perhaps this was not the meaning you went for. Perhaps record patterns were what you needed. I'll let you dig into the textbook material and resolve this.
Updated: As Andreas Rossberg suggested, I've simplified the examples a little.
Related
I am a beginner in OCaml and I'm trying to understand functors, I'm developing a "general sort function" with functors that can takes array, list, string and return an ordered list, array, string.
Can someone help me with this?
I've done this
module type Comparable= sig
type t
val compare : t -> t -> int
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
end;;
module Make_sort(S: Comparable)= struct
type t= S.t
type et= S.t list
let order t= function
|[] -> 0
|a::b -> S.fold_left (S.compare (a t)(b t)) ;;
end;;
First of all, I think that your intuition is correct but there is small confusion between the value level and the type level, ie: S.compare (a t)(b t) this expression is not valid (a and b) must be functions, this why I think that you try to give the sense of 'a t.
But, I understand what you try to do, so here is a small primer on functor (function from module to module), using a small subset of your example.
First, in order to sort we need to define how to order
Exactly as you did, we can start with a signature (COMPARABLE) which handle the "notion of comparison". For example:
module type COMPARABLE = sig
(** something which is comparable. *)
type t
(** [compare x y] returns 1 if x > y, 0 if x = 0 and -1 if x < 0 *)
val compare : t -> t -> int
end
With this signature, it is easy to define module which are comparable, for example, for Int:
module Int_comparable :
COMPARABLE with type t = int =
struct
type t = int
let compare x y =
if x > y then 1
else if x = 0 then 0
else -1
end
Note that module are candidate for a signature only if the module match the signature so de anotation : COMPARABLE with type t = int is not very necessary. And, since Int (the module from the stdlib) already implement compare and a type t, it is not necessary to define it. You can just pass Int when you need a comparable.
Now, we can define somethign "sortable"
In this very small example, something which is comparable seems to be sortable. In other words, if I have a COMPARABLE, I can sort. This relation (If I have X, I can have Y) seems quite suitable for using a functor (so, I give you a COMPARABLE and you give me something sortable). Here is a proposition:
module Sortable (C : COMPARABLE) : sig
(** if something is comparable, it is sortable. *)
type t = C.t
(** [max_of x y] returns the greater between x and y. *)
val max_of : t -> t -> t
(** [min_of x y] returns the lower between x and y. *)
val min_of : t -> t -> t
(** [sort x y] returns an ordered tuple [(max_of x y, min_of x y)]. *)
val sort : t -> t -> (t * t)
end = struct
type t = C.t
let max_of x y =
let value = C.compare x y in
if value > 0 then x
else y
let min_of x y =
let value = C.compare x y in
if value < 0 then x
else y
let sort x y =
if (C.compare x y) >= 0 then (y, x) else (x, y)
end
It is probably possible to add more helpers in the module, but I'll keep the implementation as simple as possible. So now, if I want have sortable capabilities for Int.t I can just use the module Int (from stdlib: https://caml.inria.fr/pub/docs/manual-ocaml/libref/Int.html) which has a type t and compare like this
module Sortable_int = Sortable (Int)
Now, you have the basis. For traversing using Sort, you can implement a signature (Foldable for example) and I think you have all the bricks in your hands to generalize the logic of sorting collections (modulo a little algorithmic!)
New to Ocaml so asking a very basic question.
If I have a type say type foobar = foo * bar and a variable a of type foobar. Is it possible to get just the value of foo from a with a method? Is there any other way than pattern matching? Also, in this case how would you apply pattern matching? Since the type declared is not declared as type foobar = | Foobar of foo * bar?
You can match against a pair like this:
# type intfloat = int * float;;
type intfloat = int * float
# let x : intfloat = (3, 5.5);;
val x : intfloat = (3, 5.5)
# let (int_part, _) = x in int_part;;
- : int = 3
# let (_, float_part) = x in float_part;;
- : float = 5.5
There is a function (not a method) fst that returns the first element of a pair.
# fst x;;
- : int = 3
However, the definition of fst necessarily uses pattern matching:
let fst (a, b) = a
In this definition, the construct (a, b) is a pattern that matches a pair.
Pattern matching is an essential part of OCaml, not just a fancy optional feature.
I'm working on an assignment and was given the following function:
fun label (lb,ub) =
let val s = callcc (fn k =>let fun branch c = if (c < ub)
then (pushCP (k,branch,c+1);c)
else ub
in (pushCP(k,branch,lb+1);lb)
end)
in {value=s,dom=(lb,ub)}
end;
If you put a lower and upper bound of let's say 1 and 3into this function it would print
val it = {dom=(1,3), value=1}
What I am trying to figure out is if it is at all possible to get the value. In my notes it says two possible ways of doing this would be through #value(x) or by doing val {value=a,...} = x, but I get errors both ways with this.
Any clue what I am doing wrong?
It isn't clear what you are doing wrong since you haven't reproduced what you actually tried, but your notes are correct:
- val x = {dom=(1,3), value=1};
val x = {dom=(1,3),value=1} : {dom:int * int, value:int}
The first method is to use #value to extract the value field and #dom to extract the dom field:
- #value x;
val it = 1 : int
- #dom x;
val it = (1,3) : int * int
The second method is to use pattern matching. You can extract individual fields:
- val {value = a,...} = x;
val a = 1 : int
Or you can extract both fields at once:
- val {dom = a, value = b} = x;
val a = (1,3) : int * int
val b = 1 : int
In order for the above to work, x needs to be bound to the value. Perhaps you are trying to use this with an x which hasn't been given a val binding. You would need to have something like this:
val x = label(1,3)
I don't have all the relevant code so I can't test. If the above isn't enough to answer your question, you need to provide more details.
I am new to OCaml and trying to debug some OCaml code.
Is there any function in OCaml equivalent to toString() function in Java by which most of the objects can be printed as output?
There are functions like string_of_int, string_of_float, string_of_bool in the Pervasives module (you don't have to open the Pervasives module because it's... pervasive).
Alternatively, you can use Printf to do this kind of output. For example:
let str = "bar" in
let num = 1 in
let flt = 3.14159 in
Printf.printf "The string is: %s, num is: %d, float is: %f" str num flt
There's also a sprintf function in the Printf module, so if you wanted to just create a string instead of printing to stdout you could replace that last line with:
let output = Printf.sprintf "The string is: %s, num is: %d, float is: %f" str num flt
For more complex datatypes of your own definition, you could use the Deriving extension so that you woudn't need to define your own pretty-printer functions for your type.
If you use Core and the associated Sexplib syntax extension, there are pretty good solutions to this. Essentially, sexplib auto-generates converters from OCaml types to and from s-expressions, providing a convenient serialization format.
Here's an example using Core and Utop. Make sure you follow the following instructions for getting yourself set up to use Core: http://realworldocaml.org/install
utop[12]> type foo = { x: int
; y: string
; z: (int * int) list
}
with sexp;;
type foo = { x : int; y : string; z : (int * int) list; }
val foo_of_sexp : Sexp.t -> foo = <fun>
val sexp_of_foo : foo -> Sexp.t = <fun>
utop[13]> let thing = { x = 3; y = "hello"; z = [1,1; 2,3; 4,2] } ;;
val thing : foo = {x = 3; y = "hello"; z = [(1, 1); (2, 3); (4, 2)]}
utop[14]> sexp_of_foo thing;;
- : Sexp.t = ((x 3) (y hello) (z ((1 1) (2 3) (4 2))))
utop[15]> sexp_of_foo thing |> Sexp.to_string_hum;;
- : string = "((x 3) (y hello) (z ((1 1) (2 3) (4 2))))"
You can also generate sexp-converters for un-named types, using the following inline quotation syntax.
utop[18]> (<:sexp_of<int * float list>> (3,[4.;5.;6.]));;
- : Sexp.t = (3 (4 5 6))
More detail is available here: https://realworldocaml.org/v1/en/html/data-serialization-with-s-expressions.html
Given a type:
type coords = int * int
The following works:
# let c : coords = 3, 4;;
val c : coords = (3, 4)
I would also like to be able to do:
# let (x, y) : coords = 3, 4;;
let (x, y) : coords = 3, 4;;
Error: Syntax error
But it complains about a syntax error on :. Is this syntactically possible?
The syntax let x : t = … is the no-argument case of the more general syntax
let f a1 … an : t = …
where t is the return type of the function f. The identifier f has to be just an identifier, you can't have a pattern there. You can also write something like
let (x, y) = …
Here (x, y) is a pattern. Type annotations can appear in patterns, but they must be surrounded by parentheses (like in expressions), so you need to write
let ((x, y) : coords) = …
Note that this annotation is useless except for some cosmetic report messages; x and y still have the type int, and (x, y) has the type int * int anyway. If you don't want coordinates to be the same type as integers, you need to introduce a constructor:
type coords = Coords of int * int
let xy = Coords (3, 4)
If you do that, an individual coordinate is still an integer, but a pair of coordinates is a constructed object that has its own type. To get at the value of one coordinate, the constructor must be included in the pattern matching:
let longitude (c : coords) = match c with Coords (x, y) -> x
The syntax
let x : t = ...
means that you are, in most cases needlessly, telling the compiler that the type of the name x is t (or maybe you just want to add this type information for readability purposes). In your example:
let (x,y) : coords =
you have to ask yourself: what is the name whose type is coords? Clearly you define no such name, the type of x is int and so is the type of y. There's no name with type coords on the left side. If you already have a coords value, you can split it up as below:
# type coords = int*int ;;
type coords = int * int
# let c:coords = 3,4 ;;
val c : coords = (3, 4)
# let x,y = c;;
val x : int = 3
val y : int = 4
In the above example on the line
let c: coords = 3,4 ;;
you are actually letting the compiler that the name c should be assigned a coords type (otherwise int*int will be used as the type).