What's wrong about this function? - ocaml

let minus = function
| Int.min_value, _ | Int.max_value, _ | _, Int.min_value | _, Int.max_value -> 0
| x, y -> x - y
Error: Parse error: [module_longident] expected after "." (in
[module_longident])
I can't see anything wrong.
I did this in utop with Core.Std opened

Int.min_value and Int.max_value are values, not constructors (names of constructors are capitalized, names of values are not).
You can't use values in a pattern matching, you can only use constructors.
The good code is
let minus (x, y) =
if x = Int.min_value
|| x = Int.max_value
|| y = Int.min_value
|| y = Int.max_value
then
0
else
x - y
your wrong code is equivalent to
let min_value = -1000000
let max_value = 1000000
let minus = function
| min_value, _ | max_value, _ | _, min_value | _, max_value -> 0
| x, y -> x - y
which compiles because it uses correct names (not names from a different module) but produces the wrong result (always 0).

Related

How to match multiple conditional patterns with one result?

Attempting to compile the following function causes an error:
let balance (left : 'a t) (ele : 'a) (right : 'a t) : 'a t =
match left,ele,right with
| N (d',N (_,a,x,b),y,c),z,d when d' - depth d > 1 && ele < y
| N (d',a,x,N (_,b,y,c)),z,d when d' - depth d > 1 && ele > x
| a,x,N (d',N (_,b,y,c),z,d) when d' - depth a > 1 && ele < z
| a,x,N (d',b,y,N (_,c,z,d)) when d' - depth a > 1 && ele > y
-> new_node (new_node a x b) y (new_node c z d)
| _ -> new_node left ele right
However, both of the following functions will compile without issue:
let balance (left : 'a t) (ele : 'a) (right : 'a t) : 'a t =
match left,ele,right with
| N (d',N (_,a,x,b),y,c),z,d
| N (d',a,x,N (_,b,y,c)),z,d
| a,x,N (d',N (_,b,y,c),z,d)
| a,x,N (d',b,y,N (_,c,z,d))
-> new_node (new_node a x b) y (new_node c z d)
| _ -> new_node left ele right
let balance (left : 'a t) (ele : 'a) (right : 'a t) : 'a t =
match left,ele,right with
| N (d',N (_,a,x,b),y,c),z,d when d' - depth d > 1 && ele < y
-> new_node (new_node a x b) y (new_node c z d)
| _ -> new_node left ele right
How can I get the behavior specified in the first block? Obviously, I could copy the seventh line to each of the preceding patterns, but I'd prefer not to do so.
It's true, this is a limitation of OCaml patterns.
When you write this:
match x with
| 1
| 2 -> f x
You're actually writing just one pattern that looks like this:
match x with
| (1 | 2) -> f x
So this (if it were allowed):
match x with
| 1 when a
| 2 when b -> f x
would be equivalent to something like this:
match x with
| (1 when a | 2) when b -> f x
In other words, what you're trying to do is add when clauses into the middle of a pattern. This isn't supported. They're just a feature of match, not of patterns in general.
As an addendum to what Jeffrey Scofield has already said, beware the following trap.
match 42 with
| 1
| n when n mod 2 = 0 -> "foo"
| n -> "bar"
Or equivalently:
match 42 with
| (1 | n) when n mod 2 = 0 -> "foo"
| n -> "bar"
Both get you this error:
Error: Variable n must occur on both sides of this | pattern
A when conditional guard has to work for either pattern. That's why the following will work.
match (3, 2) with
| (1, n)
| (3, n) when n mod 2 = 0 -> "foo"
| n -> "bar"
Equivalently:
match (3, 2) with
| ((1, n) | (3, n)) when n mod 2 = 0 -> "foo"
| n -> "bar"
Be prepared for compiler warnings if you bind the same name to different values using patterns joined with |.

How can I divide two numbers in ML defined as a datatype?

I'm trying to write a recursive function in SML that receives two natural numbers n1,n2 and returns the result of n1 div n2
The datatype natural is defined as follows:
datatype natural = zero | Succ of natural
I want to write it in terms of the new datatype , or in other words, not by converting them to their regular form and converting back the result.
Any ideas how division is done in this definition?
You could start by defining subtraction:
exception Negative
fun sub (a, zero) = a
| sub (zero, b) = raise Negative
| sub (Succ a, Succ b) = sub (a, b)
From here, it should be pretty easy to simply count how many times you can subtract n2 from n1 without going negative. In particular, this equation should help:
n1 div n2 = 1 + (n1 - n2) div n2
I'll leave the rest to you.
Similar to Sam Westrick's definition, "number of times you can subtract n2 from n1 without going negative", you could also do integer division with addition and greater-than using the definition, "number of times you can add n2 to itself before it is greater than n1."
datatype nat = Z | S of nat
fun gt (S x, S y) = gt (x, y)
| gt (S _, Z) = true
| gt (Z, _) = false
fun add (x, Z) = x
| add (x, S y) = add (S x, y)
fun divide (_, Z) = raise Domain
| divide (x, y) = (* ... *)
Addition might seem like a conceptually simpler thing than subtraction. But greater-than is a more expensive operator than determining when a number is negative, since the case is incurred by induction, so Sam's suggestion would be more efficient.
You might test your solution with the following tests:
fun int2nat 0 = Z
| int2nat n = S (int2nat (n-1))
fun nat2int Z = 0
| nat2int (S n) = 1 + nat2int n
fun range (x, y) f = List.tabulate (y - x + 1, fn i => f (i + x))
fun divide_test () =
let fun showFailure (x, y, expected, actual) =
Int.toString x ^ " div " ^ Int.toString y ^ " = " ^
Int.toString expected ^ ", but divide returns " ^
Int.toString actual
in List.mapPartial (Option.map showFailure) (
List.concat (
range (0, 100) (fn x =>
range (1, 100) (fn y =>
let val expected = x div y
val actual = nat2int (divide (int2nat x, int2nat y))
in if expected <> actual
then SOME (x, y, expected, actual)
else NONE
end))))
end

how to rewrite code using tail recursion

I just looking for a little advice, how to rewrite code using tail recursion
open Core.Std;;
let rec dig x =
match x with
| 0 -> []
| _ -> x :: dig (x - 1)
;;
let () =
let numbers = dig 10 in
List.iter ~f:(Printf.printf "%d, ") numbers;
Printf.printf "\n";
;;
Any advice will be helpful
let dig x =
let rec f x s =
match x with
| 0 -> s
| _ -> f (x-1) (x::s)
f x []
Is this what you want? It's using tail recursion.
Edit:
for a decreasing seq, just replace (x::s) with (List.append s [x]) or (s # [x]) but it's NOT a good idea,and List.rev is better:
let dig x =
let rec f x s =
match x with
| 0 -> s
| _ -> f (x-1) (s # [x])
f x []
let dig x =
let rec f s z =
if z = x then s
else f (z::s) (z+1)
in
f [] 0
not sure if this floats your boat: You may have to tweak the border cases depending if you want 0 or the starting number included.
If you don't want to use List.rev after building the list backwards (which in my opinion is perfectly fine), nor starting your recursion with 0 instead of n, you can use some kind of continuation:
let dig2 x =
let rec aux x kont =
match x with
| 0 -> kont
| _ -> aux (x-1) (fun l -> kont (x::l))
in
aux x (fun l -> l) [];;
Basically each step returns a function that, given the list built by the remaining steps, will append x to it. We start the recursion with the identity function since we don't have anything to build yet. Then, when we exit from the recursion, we thus just have to apply the empty list to the obtained function.
Well, it seems to can have multiple solutions
open Core.Std;;
let rec digtail ?(l=[]) x =
match x with
| 0 -> l
| _ -> digtail ~l: (l # [x]) (x - 1)
;;
let () =
let numbers = digtail 10 in
List.iter ~f:(Printf.printf "%d, ") numbers;
Printf.printf "\n";
;;
Thanks to all, you helped a lot.

Haskell List With Guards error

i am trying to write a very simple function in haskell to change a value in a list depending on an input as follows
update_game :: [Int] -> Int -> Int -> [Int]
update_game (x:xs) row take_amnt | row == 1 = x - take_amnt:xs
| row == 2 = x : head(xs) - take_amnt : tail(xs)
| row == 3 = x : head(xs) : last(xs) - take_amnt`
the first two cases work fine, however the last case is causing me problems and im not sure why, the errors i get are :
http://i.stack.imgur.com/jpT8b.png
http://i.stack.imgur.com/tlz5t.png
The second argument to : should be a list, but last(xs) - take_amnt apparently yields only a single element. Try
row == 3 = x : head(xs) : [last(xs) - take_amnt]
The second parameter in ":" should be a list, last(xs) - take_amnt gives an element only.
wrap it in "[]" which would be [last(xs) - take_amnt]
last(xs) - take_amnt
is an Int, but the second argument of (:) must be a list, since (:) :: a -> [a] -> [a].
If your lists are always three elements long (but then you should probably use a tuple instead of a list), as it seems, wrapping that in a [ ] would solve it with the correct semantics,
update_game :: [Int] -> Int -> Int -> [Int]
update_game (x:xs) row take_amnt | row == 1 = x - take_amnt:xs
| row == 2 = x : head(xs) - take_amnt : tail(xs)
| row == 3 = x : head(xs) : [last(xs) - take_amnt]
However, it would be better to pattern-match accordingly
update_game [x,y,z] 1 take_amnt = [x - take_amnt, y, z]
update_game [x,y,z] 2 take_amnt = [x, y - take_amnt, z]
update_game [x,y,z] 3 take_amnt = [x, y, z - take_amnt]
update_game _ _ _ = error "Invalid input"
or make it generic without pattern matching
update_game xs index take_amnt = zipWith (-) xs (replicate (index-1) 0 ++ take_amnt : repeat 0)

How to check whether two values are created with the same constructor?

let's say I have
type t = A of int | B of int
let xx = A(2);;
let yy = A(3);;
and I want to test if the constructors of xx and yy are equal,
is there an easy way to do this ? Instead of having to
match xx with
A _ ->
(match yy with A _ -> true | B _ -> false)
| B _ ->
(match yy with A _ -> false | B _ -> true);;
which gets quite messy when there many constructors on a type
You can rewrite the above to, somewhat simpler:
match xx, yy with
| A _, A _
| B _, B _ -> true
| (A _ | B _), _ -> false
but I'm not aware of a solution without enumerating all the constructors.
This is possible, sort of, through the Obj module. Analyzing objects through the Obj functions, if done properly, won't crash your program; but you need to be careful if you want to get meaningful results.
let equal_constructors (x : 'a) (y : 'a) =
let r = Obj.repr x and s = Obj.repr y in
if Obj.is_int r && Obj.is_int s then (Obj.obj r : int) = (Obj.obj s : int) else
if Obj.is_block r && Obj.is_block s then Obj.tag r = Obj.tag s else
false
When called on values of a variant type (not a polymorphic variant type), this function returns true if the two values both have the same zero-argument constructor or both have the same 1-or-more-argument constructor, and false otherwise. The type system won't prevent you from instanciating equal_constructors at other types; you'll get a true or false return value but not necessarily a meaningful one.
Another way of doing this that can work well is to create another type that corresponds to the tags, and use that type.
type t = A of int | B of int
module Tag = struct type t = A | B end
let to_tag = function A _ -> Tag.A | B _ -> Tag.B
let tags_are_equal x y =
to_tag x = to_tag y