How to partially match a pattern in OCaml - 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.

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

SML: Error: match redundant and Warning:match nonexhaustive

I am getting both of these issues for this function:
fun funion([(x:int list,y:bool list)]) =
let
fun join(nil,final) = final |
join(x::xs,final) = join(xs,union(x,final)) |
join(_,final) = final
in
join([(x,y)],(nil,nil))
end;
Here is the error:
sets.sml:30.6-32.27 Error: match redundant
(nil,final) => ...
(x :: xs,final) => ...
--> (_,final) => ...
sets.sml:28.5-35.4 Warning: match nonexhaustive
(x,y) :: nil => ...
Does anyone know what might be going on here? I also tried join(_) but that did not work either. Not sure what the problem is here.
uncaught exception Error
Edit:
Here is the definition of union:
fun union((w:int list,x:bool list),(y:int list,z:bool list)) =
let
fun join((nil,nil),final) = final |
join((w::ws,x::xs),(intfinal,boolfinal)) = if x andalso elementOf(w,(intfinal,boolfinal))=false then join((ws,xs),(w::intfinal,true::boolfinal)) else join((ws,xs),(intfinal,boolfinal)) |
join(_,final) = final
in
join((w,x),join((y,z),(nil:int list,nil:bool list)))
end;
I gather that funion is supposed to have type
(int list * bool list) list -> (int list * bool list)
But -- you only provide a definition for lists of length 1, which gives a non-exhaustive list warning.
For the inner function join you provide a definition first for patterns of the form (nil, final) and then for patterns of the form (x::xs,final). Since the first component is either empty or matches the pattern x::xs and any list whatsoever matches final, any further pattern is redundant. Perhaps you want the three patterns
1) (nil,ys)
2) (xs,nil)
3) (xs,ys)
A final remark -- if you are happy with union -- why not just use it with foldl or foldl if you have a list of (int list * bool list) and what the union of them all?
"Error: match redundant" means that a pattern doesn't match anything that previously-tested matches wouldn't also match. In your case, you have the match-pattern (nil, final) (which matches any pair whose first element is the empty list) and the match-pattern (x::xs, final) (which matches any pair whose first element is a non-empty list), which together cover all cases . . . and then you have the match-pattern (_, final), which doesn't match anything new. Technically this doesn't need to be an error — the compiler could just issue a warning and discard this match — but it's such a serious warning that SML/NJ treats it as an error.
"Warning: match nonexhaustive" means that your match-patterns don't cover all cases. In your case, the match-pattern ([(x:int list,y:bool list)]) can only match a single-element list. (You probably just meant to write (x:int list, y:bool list), without the [...] notation to match a list of hardcoded length.)

Getting value of variant in Ocaml

Say I have a variant v defined by:
type value =
| Value of int
| Error of string;;
I want to do something if v is a Value and something else if v is an Error, how can I determine this and perform different behaviors based on it?
That's what the match expression is for:
match v with
| Value n -> (* Something with n *)
| Error s -> (* Something with s *)
(Insofar as OCaml is a functional language, it might be better to think in terms of values rather than behaviors. But OCaml can also be an imperative language if you wish.)

Int list to int OCaml

I am new to OCaml, so I am learning the basics. I am writing a function that determines whether a list contains a given integer.
let rec int_member (x: int) (l: int list) : bool
begin match l with
| [] -> false
| hd :: rest -> x = hd || int_member rest x
end
as a test case...
let test (): bool =
(int_member 1 [1;2;3]) = true
;; run_test "contains 1 [1;2;3]" test
I am getting an error saying that "this expression has type int list but an expression was expected of type int". How can I fix this?
If you look at your recursive call, you should see that you're not passing the arguments quite right! Otherwise this code is quite good. (I see a missing =, and also using begin and end isn't very idiomatic OCaml here. You can just leave them out.)
int_member rest x
The first argument to int_member should be an int. You're passing an int list as the first argument. That's what the error message is complaining about.
You simply switched around the order of the arguments.
PS: The begin ... end in your code is superfluous.

What does :: and ' mean in oCaml?

What doesx :: xs' mean?
I dont have much functional experience but IIRC in F# 1 :: 2 :: 3 :: [];; creates an array of [1,2,3]
so what does the ' do?
let rec sum xs =
match xs with
| [] -> 0
| x :: xs' -> x + sum xs'
I think sepp2k already answered most of the question, but I'd like to add a couple of points that may clarify how F#/OCaml compiler interprets the code and explain some common uses.
Regarding the ' symbol - this is just a part of a name (a valid identifier starts with a letter and then contains one or more letters, numbers or ' symbols). It is usually used if you have a function or value that is very similar to some other, but is in some way new or modified.
In your example, xs is a list that should be summed and the pattern matching decomposes the list and gives you a new list (without the first element) that you need to sum, so it is called xs'
Another frequent use is when declaring a local utility function that implements the functionality and takes an additional parameter (typically, when writing tail-recursive code):
let sum list =
let rec sum' list res =
match list with
| [] -> res
| x::xs -> sum' xs (res + x)
sum' list 0
However, I think there is usually a better name for the function/value, so I try to avoid using ' when writing code (I think it isn't particularly readable and moreover, it doesn't colorize correctly on StackOverflow!)
Regarding the :: symbol - as already mentioned, it is used to create lists from a single element and a list (1::[2;3] creates a list [1;2;3]). It is however worth noting that the symbol can be used in two different ways and it is also interpreted in two different ways by the compiler.
When creating a list, you use it as an operator that constructs a list (just like when you use + to add two numbers). However, when you use it in the match construct, it is used as a pattern, which is a different syntactic category - the pattern is used to decompose the list into an element and the remainder and it succeeds for any non-empty list:
// operator
let x = 0
let xs = [1;2;3]
let list = x::xs
// pattern
match list with
| y::ys -> // ...
The ' is simply part of the variable name. And yes foo :: bar, where foo is an element of type a and bar is a list of type a, means "the list that has foo as its first element, followed by the elements of bar". So the meaning of the match statement is:
If xs is the empty list, the value is 0. If xs is the list containing the item x followed by the items in xs' the value is x + sum xs'. Since x and xs' are fresh variables, this has the effect that for any non empty list, x will be assigned the value of the first element and xs' will be assigned the list containing all other elements.
Like others have said, the ' is a carryover from mathematics where x' would be said as "x prime"
It's idiomatic in ML-family languages to name a variable foo' to indicate that it's somewhat related to another variable foo, especially in recursions like your code sample. Just like in imperative languages you use i, j for loop indices. This naming convention may be a little surprising since ' is typically an illegal symbol for identifiers in C-like languages.
What does x :: xs' mean?
If you have two variables called x and xs' then x :: xs' creates a new list with x prepended onto the front of xs'.
I dont have much functional experience but IIRC in F# 1 :: 2 :: 3 :: [];; creates an array of [1,2,3]
Not quite. It's a list.
so what does the ' do?
It is treated as an alphabetical character, so the following is equivalent:
let rec sum xs =
match xs with
| [] -> 0
| x :: ys -> x + sum ys
Note that :: is technically a type constructor which is why you can use it in both patterns and expressions.