Scope of variables in OCaml - ocaml

When I have e.g.
type 'a inf_list = Cons of 'a * (unit -> inf_list);;
(* inf_list starting at n*)
let rec num n = Cons (n, fun () -> num (n+1));;
How does the following work:
let Cons (cur, rest_l) = integers 1;;
let x = cur;;
let y = (rest_l());;
normally the format is let <variable/function-name> = <definition>.
Here it is let <type (x,y) = <expression>. So generally speaking how does this work?

First of all, the form for let is let <pattern> = <expression>. You can have many things in a let besides variable and function names. A name is just one possible kind of pattern.
Second, the subexpression Cons (cur, rest_l) is not a type. It's a pattern that matches a value of type 'a inf_list. The head of the list will be bound to cur and the rest of the list will be bound to rest_l.
So your example has the expected form for a let. And it binds the two names cur and rest_l in the global scope.

As an addendum to Jeffrey's answer, please note that the as keyword can be used to bind a name to a pattern.
In your case:
let Cons (cur, rest_l) as lst = integers 1;;
Where lst now refers to the entire inf_list value as well as binding names to its constituent values.

Related

why is a definition like this not producing an error in OCaml?

let f (x :: []) = [1;2];;
I don't understand the structure of this function.
Normally a function is declared like this:
let <function name> <arguments> = <function definition> But here
we give the function f a constant as an argument, namely [x], and then do
nothing with this argument. Instead, we assign the constant [1;2] to the function f?
To illustrate why having patterns in a function definition is useful, here are few examples of exhaustive patterns in arguments. The first common case is tuple:
let f (x,y) = x + y
In the code above,(x,y) is a pattern that binds the first and second element of a couple to the x and y variable respectively.
There is an equivalent construction for records
type vec2 = {x: float; y:float}
let f { x; _ } { y; _ } {x=x'; y = y' } = x +. y +. x' + y'
In this case {x; _}, {y; _ }, { x=x'; y=y'} are both exhaustive patterns.
For ordinary variants, it is less frequent to have useful and exhaustive patterns, but this can happen:
let f (x::_, _ | [], x) = x
Here, in this case we are either extracting the first element of the list in the first element of the tuple if the list is not empty, or the second element of the tuple.
Those cases are more frequent when using GADTs or empty types that makes it possible to have some branches of an algebraic not inhabited for a specific subtype.
For instance, the pattern in
type empty = |
let f (None:empty option) = ()
is exhaustive because the only possible value of the type empty option is None.
utop # let f x :: [] = [1;2];;
Error: Syntax error
This does give me an error. The following will compile.
let f (x :: []) = [1; 2]
But produces a warning about incomplete pattern match, because a list can have zero or any number of elements. A list with one element is just one specific example.
utop # let f (x :: []) = [1; 2];;
Line 1, characters 6-24:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
_::_::_
val f : 'a list -> int list = <fun>
It's worth noting that [x] is not a constant in a function like this. It is binding the name x to the one element in the list, whatever that happens to be.
Consider:
utop # let foo [x] = x;;
Line 1, characters 8-15:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
_::_::_
val foo : 'a list -> 'a = <fun>
utop # foo [42];;
- : int = 42
Of course, this is a silly function, since x is never used by the function. You might just have written the following, using _ to indicate a value that we don't care enough about to give a name to.
let foo [_] = [1; 2]

OCaml initializing list in loop for

I am a beginner with OCaml. I would like to skip the first element of my list.
Here is my list:
let l = [1;2;3;4;5;6;7;2;1];;
I want to use this in my FOR:
let l = List.tl l;
here is my full code:
let l = [1;2;3;4;5;6;7;2;1];;
let n = 1;;
let counter = ref 0;;
for i = 0 to (List.length l) do
if List.hd l = n then counter := !counter + 1;
print_int(!counter);
print_string("\n");
let l = List.tl l
done;;
But I have errors in the DONE and it says syntax error.
Can anyone help me please?
Your problem is that let always requires a matching in. The full expression looks like this:
let var = expr1 in expr2
Since you're missing the in part, you get a syntax error.
However, the deeper problem is that you're trying to modify the value of l. The way you have defined l, it's immutable. You can't change its value. If you want to be able to change its value you can define it as a reference, as you have done for counter.
(There is another form of let used at the top level of a module. This form doesn't have a matching in. But your code isn't defining a top-level name, so this is not relevant.)

Lazy list of x, f x, f (f x),

Batteries.LazyList allows one to define lazy lists. I would like to define a lazy list consisting of x, f x, f (f x), f (f (f x)), etc.
Based on comments in the module documentation, it appears that from_loop is the function I want:
"from_loop data next creates a (possibly infinite) lazy list from the successive results of applying next to data, then to the result, etc."
This description suggests that if I wanted a lazy list of non-negative integers, for example, I could define it like this:
let nat_nums = from_loop 0 (fun n -> n + 1)
However, this fails because the signature of from_loop is
'b -> ('b -> 'a * 'b) -> 'a LazyList.t
so the next function has signature ('b -> 'a * 'b). In utop, the error message underlines n + 1 and says
Error: This expression has type int but an expression was expected of type 'a * int
I don't understand what 'a is supposed to be. Why is the next function supposed to return a pair? Why is the type of the list supposed to be a 'a LazyList.t? Shouldn't the type of the elements be the same as the type of the argument to the next function? The description of the function doesn't make the answers clear to me.
In case it's helpful, my conception of what I'm trying to do comes from Clojure's iterate. In Clojure I could create the above definition like this:
(def nat-nums (iterate (fn [n] (+ n 1)) 0))
The function passed to from_loop has to return a pair. The first element of the pair is the value you want to return. The second element of the pair is the state required to calculate the next element later on.
Your code:
(fun n -> n + 1)
Just calculates the next element of the lazy list, it doesn't return the state required for the next call. Something like this is what is wanted:
(fun n -> (n, n + 1))
(This will return a list starting with 0, which I think is what you want.)
This formulation is more flexible than your clojure example, because it allows you to maintain arbitrary state distinct from the values returned. The state is of type 'b in the type you give for from_loop.
I don't have Batteries right now, so I can't try this out. But I think it's correct based on the types.
It turns out that the function that I really wanted was LazyList.seq, not from_loop. While from_loop has its uses, seq is simpler and does what I wanted. The only trick is that you have to provide a third argument which is a termination test that returns false when the list should end. I wanted an infinite list. One can create that using use a termination function that always returns true:
let nat_nums = seq 0 (fun n -> n + 1) (fun _ -> true);;
LazyList.to_list (LazyList.take 8 nat_nums);;
- : int list = [0; 1; 2; 3; 4; 5; 6; 7]

Implementing multiple if statements in OCaml

So I am a little new to OCaml and I am trying to figure out a way for my function to check multiple conditions and modify a variable if any of those conditions are true
rough pseudo code would be
var list = []
if cond1 then 1::list
if cond2 then 2::list
etc
but from what I am able to tell once you enter an if statement you stay in it until it returns a value to the function. Is there a way around this limitation? Thanks for your time, tips or hints are greatly appreciated as I would love to understand the language
OCaml variables are immutable, you can't change their values. So you need to think of this a different way. One reasonable thing would be to have a function whose value is equal to a supplied list with something added to the front:
let f list =
if cond1 then 1 :: list
else if cond2 then 2 :: list
else 3 :: list
Note that if in OCaml is an expression, i.e., it has a value. It's similar to the ?: ternary operator in languages influenced by C.
Here is an OCaml session that shows a function like this. It's just an example, this isn't a useful function:
$ ocaml
OCaml version 4.01.0
# let f list =
if List.length list > 3 then 1 :: list
else if List.length list > 1 then 2 :: list
else 3 :: list ;;
val f : int list -> int list = <fun>
# f [];;
- : int list = [3]
# f [1;2];;
- : int list = [2; 1; 2]
Update
If you want to apply the ifs all the time the code looks like this:
let f list =
let list' = if cond1 then 1 :: list else list in
let list'' = if cond2 then 2 :: list' else list' in
let list''' = if cond3 then 3 :: list'' else list'' in
list'''
You can capture the repeated pattern in its own function:
let f list =
let cpfx cond pfx l = if cond then pfx :: l else l in
cpfx cond3 3 (cpfx cond2 2 (cpfx cond1 1 list))
If you want to have a sequence of if statements, each if must return unit. You can use a reference to your list to make it mutable, put semicolons after each if statement and return the referenced list at the end:
let f list =
let list = ref list in
if cond1 then list := 1 :: !list;
if cond2 then list := 2 :: !list;
[...]
!list
;;
The given list will not be modified, there is just a new variable called list that shadows the original one within the function definition.

OCaml - Add a new tuple, containing a list of tuples, to that list

I'm writing an interactive calculator in OCaml with some simple commands. Users should be able, among other things, to define their own simple functions (mathematical functions), for instance
let f(x) = x
let g(x) = 2*f(x)
Now, the functions should be handled like in functional languages, that means they should remember their time-of-creation environment. That means, that with a function I have to keep a closure of its environment, which is functions and variables.
I keep currently defined functions in a list of tuples formed like (functions_present_at_the_time_of_creation, variables_present_at_the_time_of_creation, function_name, function_argument_names, function_formula). When I try to add a new function to the list of functions (let's assume, that it's not currently defined and I don't have to overwrite anything), I recurrently iterate to the end of the list of functions and there would like to add a new tuple.
The problem is, assuming my current functions list is of type (a*b*c*d*e) list when i try to add a tuple with itself to the end of it, it changes its type to ((a*b*c*d*e) list*f*g*h*i) list. What can I do to be able to perform such addition of a list to itself, encapsulated in a tuple?
Here's some simple SSCCE I wrote while trying to find a workaround to this issue.
let rec add_to_end list list_copy dummy = match list with
| [] -> [(list_copy, dummy)]
| h::t -> h::(add_to_end t list_copy dummy)
let add list dummy = add_to_end list list dummy
This one tries to do it with a copy of the list. The following one is written without using of a copy (both of these examples don't work, of course):
let rec add_to_end list dummy = match list with
| [] -> [(list, dummy)]
| h::t -> h::(add_to_end t dummy)
The first example doesn't work when trying to use the function add, but when doing it for instance this way (in the interpreter):
let l = [];;
let l = add_to_end l l 1;;
let l = add_to_end l l 2;;
let l = add_to_end l l 3;;
Then it works fine. I'd appreciate any help, I may think about changing the design also, any proposals are very welcome.
Edit: Here's the output of the above commands:
# let l = [];;
val l : 'a list = []
# let l = add_to_end l l 1;;
val l : ('a list * int) list = [([], 1)]
# let l = add_to_end l l 2;;
val l : (('a list * int) list * int) list = [([], 1); ([([], 1)], 2)]
# let l = add_to_end l l 3;;
val l : ((('a list * int) list * int) list * int) list =
[([], 1); ([([], 1)], 2); ([([], 1); ([([], 1)], 2)], 3)]
It's hard to tell whether you're aware that OCaml lists are immutable. You can't add a value to the end of an existing list. An existing list can never be changed. You can create a new list with a value added to the end. If you do this, I don't see why you would want to add a pair to the end consisting of the list and the new value. I suspect you're thinking about it wrong. Here's a function that takes a list and an integer and adds the integer to the end of the list.
# let rec addi i list =
match list with
| [] -> [i]
| h :: t -> h :: addi i t
;;
val addi : 'a -> 'a list -> 'a list = <fun>
# let x = [1;2;3];;
val x : int list = [1; 2; 3]
# addi 4 x;;
- : int list = [1; 2; 3; 4]
# x;;
- : int list = [1; 2; 3]
#
The function returns a new list with the value added to the end. The original list isn't changed.
As a side comment, it's much more idiomatic to add values to the front of a list. Repeatedly adding to the end of the list is slow--it gives quadratic behavior. If you want the other order, the usual thing to do is add everything to the front and then reverse the list--this is still linear.
Edit
Apparently you really want a function that looks something like this:
let f a list = list # [(list, a)]
This is not realistically possible, the types don't work out right. A list can contain things of only one type. So you can conclude that the type of the list t is the same as the type (t, v) list, where v is the type of a. This is a recursive type, not something you would really want to be working with (IMHO).
You can actually get this type in OCaml using -rectypes:
$ ocaml -rectypes
OCaml version 4.00.0
# let f a list = list # [(list, a)];;
val f : 'a -> (('b * 'a as 'c) list as 'b) -> 'c list = <fun>
#
But (as I say) it's something I would avoid.
Edit 2
Now that I look at it, your first code sample avoids requiring a recursive type because you
specify two different copies of the list. Until you call the function with the same list, these are potentially different types. So the function type is not recursive. When you call with two copies of the same list, you create a new value with a type that's different than the type of the list. It only works because you're using the same name l for different values (with different types). It won't work in a real program, where you'd need a single type representing your list.
As another side comment: the beauty of adding values to the beginning of a list is that the old value of the list is still there. It's the tail of the new list. This seems lot closer to what you might actually want to do.