Is there a shorthand to match e.g. "anything of int" - ocaml

Say I have a variant like:
type myvar = A of int | B of int
I can write a function like:
let myvar_to_int = function
| A i -> i
| B i -> i
Let's say I have lots more elements in the variant, all <something> of int ...
Is there any shorthand for writing the to_int function? e.g. a way to express <anything> of int in a match case?
(In other places in the code I want to be able to distinguish my As from Bs and match on them explicitly still)

If every variant has an int then you really have a pair of distinct values:
type ab = A | B
type myvar = ab * int
let myvar_to_int = snd
Otherwise, no there's no way to do what you want. You can write slightly more compactly:
let myvar_to_int = function
| A i | B i -> i

Related

Call 2 or more functions inside a match expression

I am a beginner in OCaml. I am curious to know how, syntactically speaking, call two functions, or more, within a match expression. Or is that possible at all?
For example :
let rec foo l:list =
match l with
| [x,y] -> (foo1 x) (foo2 y)
| _ -> doSome
I have tried using the ; operator but that seems to be used for something else. I have tried different combinations of bracketing but in all cases I get
This is not a function it cannot be applied under foo1 x.
You just need a semicolon (no begin/end). You don't need the parentheses (they don't hurt but they're not especially idiomatic OCaml).
let rec foo l : 'a list = match l with
| [x,y] -> foo1 x; foo2 y
| _ -> doSome

How to partially match a pattern in OCaml

I have a list lst of objects of type value where
type value = A of int | B of bool | C of string
In doing some matching on the the list, I tried to write
match lst with
| A x :: val :: tl -> ...
and got an exception saying that in the variable val a pattern was expected. I am assuming this is because in the head of the list I matched on a value variant, but for val I wanted to capture all possible next entries in the list. I can think of some ways around them, like writing several cases for the several variants of val. But since I want to do the same basic thing no matter what val is, that seems like a very inelegant solution. Is there a better solution?
Elaborating an answer based on glennsl's comment, I assume this snippet entered into the top level is reproducing the syntax error you're hitting:
since val is a reserved keyword, it is not legal to use it in pattern matches. The error is saying that the underlined token val is triggering a syntax error since it is expecting something that could be part of a pattern.
The following should compile without any problems (using some random values for example):
type value = A of int | B of bool | C of string
match [A 1; B true; C "foo"] with
| A x :: v :: tl -> Some (x, v)
| _ -> None
And this is simply due to the replacement of the keyword val with the variable v in the pattern.

Variant vs GADT approach

In OCaml, I want to define a function f that accepts an input to update a record x. Among the following two approaches, I'm interested whether one has an advantage over the other (readability aside).
Variant approach
type input =
| A of int
| B of string
let f x = function
| A a -> { x with a }
| B b -> { x with b }
GADT approach
type _ input =
| A : int input
| B : string input
let f (type t) x (i: t input) (v: t) =
match i with
| A -> { x with a = v }
| B -> { x with b = v }
ADT pros:
Straightforward, no need for type annotations or anything fancy
Writing a function of type string -> input is straightforward.
GADT pros:
Avoid one layer of boxing.
However, this is completely negated if you need a parsing functions, which would force you to pack things under an existential.
To be more precise, the GADT version can be seen as a decomposition of the ADT version. You can transform one into the other in a systematic way, and the memory layout will be similar (with the help of a small annotation):
type a and b and c
type sum =
| A of a
| B of b
| C of c
type _ tag =
| A : a tag
| B : b tag
| C : c tag
type deppair = Pair : ('a tag * 'a) -> deppair [##ocaml.unboxed]
let pack (type x) (tag : x tag) (x : x) = Pair (tag, x)
let to_sum (Pair (tag, v)) : sum = match tag with
| A -> A v
| B -> B v
| C -> C v
let of_sum : sum -> deppair = function
| A x -> pack A x
| B x -> pack B x
| C x -> pack C x
As you noticed (non)readability of GADTs is a big drawback. Try to avoid GADTs when possibly. Easier to type and easier to read. Less complex error messages too.
Simplified at runtime they are the same. They are represented as simple ints or blocks with tag and fields and the code uses the tag to match and branch. So neither gives you an advantage there.
At compile time GADTs are more powerful as the compiler can check types in ways that ADTs don't allow. One example are existential types like the example in the other answer. So use GADTs when you can't use ADTs.

Assertion in type definition

I have some type
type my_type_name =
| A of (float * float)
| B of (float * float)
| E
;;
And I know that I have issue in my code, if p >= q in B (p, q) or A (p, q). So I want to make assertion in type, such that if I'll try to make A (5, 1) it will inform me.
Is it possible to make assertion in type constructor? How it should look like?
I'm trying to avoid something like that:
assert (p < q) ; A(p, q)
Cause I have a lot of A or B objects in code.
#Jeffrey Scofield already gave a fully accurate answer to this, but here is the example requested:
module type MY_TYPE =
sig
type my_type_name = private
| A of (float * float)
| B of (float * float)
| E
val a : float -> float -> my_type_name
val b : float -> float -> my_type_name
val e : my_type_name
end
module My_type : MY_TYPE =
struct
type my_type_name =
| A of (float * float)
| B of (float * float)
| E
let a p q = assert true; A (p, q)
let b p q = assert true; B (p, q)
let e = E
end
let () =
(* My_type.A (1., 2.); *) (* Type error - private type. *)
let x = My_type.a 1. 2. in
(* Can still pattern match. *)
match x with
| My_type.A (_, _) -> ()
| My_type.B (_, _) -> ()
| My_type.E -> ()
The body of the signature could be an .mli file instead and the body of My_type could be an .ml file. The key is that my_type_name is followed by the keyword private in MY_TYPE. This causes the direct use of the constructor at the bottom to be flagged as an error, forcing all construction to go through the functions a, b, e, where you can include assertions or arbitrary other expressions.
EDIT To make the functions look even more like the constructors, you can of course turn their arguments into tuple types. To make the module nearly transparent you can open it at the bottom. But these are matters of taste and up to you.
There's no straightforward way to put such an assertion into the type definition itself.
One good approach would be to define your type as an abstract type (in a module) and export functions for constructing values of the type. These will be the only way to produce values of the type, and you can include any assertions you like in the functions.
Update
As #antron points out, making the type private rather than abstract might be a better fit for your problem.

Finding max element in a list in SML

I am trying to find the the greatest value in a list using Standard ML. I need to use the given fold function:
fun fold f [] base = base
| fold f (x::xs) base = fold f xs (f x base);
Here is what i have so far:
fun max (x::xs) = fold (fn (a, b) => if a > b then a else 0) x (x::xs);
I have 0 in there because if the list is empty then I need to return 0;
This is only part of another function that I need to define, but I'm struggling with the fold part.
In your definition of the fold function, you require that the function f must take it's arguments in curry form, that is: f 1 1 instead of f(1,1).
As I understand, then your definition of the fold function is the right one. Thus you need to make proper changes to the anonymous function in the max function.
In SML, currying is actually just syntactic sugar. For example:
fun foo a b = a+b
would end up as (after desugaring):
val rec foo = fn a => fn b => a+b
It is also seen that the two functions has the same type:
- fun foo a b = a+b;
val foo = fn : int -> int -> int
- val rec foo = fn a => fn b => a+b;
val foo = fn : int -> int -> int
Thus the anonymous function must be define somewhat along the same lines.
Also you have mixed the arguments to fold. In the last part of the max function, you are giving the two last arguments in the reverse order.
The last problem is that your anonymous function returns 0. This screws with the invariant of you anonymous function and makes it fail in some cases. For example:
max [1,4,65,7,6];
Try to figure out why yourself.
If you really need to return 0 if the input list to max is empty, then you should pattern match that case. This also fixes the warning about "match nonexhaustive", and is the correct place to do it.
fun max [] = 0
| max (x::xs) = fold (fn a => fn b => if a > b then a else b) (x::xs) x;