I am a bit confused by infix function.
So if I define let (++) x y = ..., then ++ is an infix function. I can use it as follows:
x ++ y
(++) x y
Basically if I remove parentheses, I can put 1st parameter to its left, and 2nd to its right.
Then can I define 3 parameters, like let (++) x y z = ...?
If I do let (++) x y z = x + y + z in utop, it is ok and give me:
utop # let (++) x y z = x + y + z;;
val ( ++ ) : int -> int -> int -> int = <fun>
I can use (++) 1 2 3 and answer is 6.
But is (++) an infix function? If I want to purely use ++, how should I put x,y,z around it?
# (1 ++ 2) 3;;
- : int = 6
Although I'm not sure when you would actually want to do that...
Related
I saw let (-) x y = y - x in 1 - 2 - 3 and let rec (-) x y = y - x in 1 - 2 - 3 these two examples in a book about ocaml. When I saw the former one, I thought I understood the trick behind until I saw the latter function. It seems that the latter function is having some stack overflow problem, but why is it the case? How does ocaml evaluate these two expressions separately?
It might be helpful to rename the let bound functions.
let (-) x y = y - x
in 1 - 2 - 3
(* The above expression is equivalent to the following. *)
let f x y = y - x
in f (f 1 2) 3
(* Which reduces to the following. *)
let f x y = y - x
in 3 - (2 - 1)
Note that the function we defined, let (-) x y, is different from the function which we use in the definition, y - x. This is because let without rec doesn't bind the function name within the definition. Hence, the (-) operator in the definition is the native minus operator. Therefore, the result is 2.
Now, consider the second example.
let rec (-) x y = y - x
in 1 - 2 - 3
(* The above expression is equivalent to the following. *)
let rec f x y = f y x
in f (f 1 2) 3
Now, what does f 1 2 reduce to? It reduces to f 2 1, which reduces to f 1 2, which reduces to f 2 1, and so on ad infinitum. Now, in a language without tail call optimization this would result in a stack overflow error. However, in OCaml it should just run forever without returning.
The let expression has syntax is let <name> = <expr1> in <expr2> and it defines <name> to be bound to <expr1> in <expr2>. The <name> itself is not visible in the scope of <expr1>, in other words it is not recursive by default. And that feature could be (and often used) to give the same names the new meaning, e.g., this is the canonical OCaml code,
let example () =
let name = "Alice" in
let name = "Professor " ^ name in
print_endline name
The same technique approach is used in the let (-) x y = y - x in 1 - 2 - 3, where we redefine the (-) in terms of the original (-) operator which is still seen untouched in the scope of the y - x expression.
However, when we add the rec keyword to the let definition then the name is immediately visible in the scope of the currently defined expression, e.g.,
let rec (-) x y = y - x
(* ^ | *)
(* | | *)
(* +----------+ *)
here - in x - y refers to the currently defined function, so we have a recursive definition that says that x minus y is y minus x - a bogus definition.
So I have this function where i'm taking in two float lists and using their respective index elements to calculate this simple formula: (x-y)^2 / x for every index (0,1,2,3...)
Here is what I have so far:
let myCalc (list1: float list) (list2: float list) : float list =
List.map2 (fun x y -> (x-y)^2 / x) list1 list2
I keep getting this error: This expression was expected to have type 'float' but here has type 'string'
How come my approach listed above won't work but this example does:
let list1 = [1; 2; 3]
let list2 = [4; 5; 6]
let sumList = List.map2 (fun x y -> x + y) list1 list2
printfn "%A" sumList
Can someone explain how I can understand the difference between the code that I've written and the example code listed above? And yes, I already tried setting the List.map2 to a variable and then printing it out but that didn't work either. I think it has something to do with the way I'm doing my calculations, I just don't know what is wrong.
Also, I want my output result to be stored in a list of the respective x and y indexes. Please help.
The reason for this error is relatively simple, you are using the wrong power operator (^). In F #, and in the family of ML languages in general, this operator is a concatenation string operator. This is why you get this error, since the compiler expects to find two parameters of the string type in rvalue and lvalue for the^operator.
You must use the ** operator:
let myCalc (list1: float list) (list2: float list) : float list =
List.map2 (fun x y -> (x - y) ** 2. / x) list1 list2
2 is a literal of typeint, we have to specify that we want to use a literal value of type float for the expression, so this gives us this:2.
In Reason (and OCaml), there is a non-traditional way of passing arguments using the |> operator. What is the convention for when it should be used? I am currently using it all over the place just because of how novel I find it.
Using |> (forward pipe) is helpful for showing the order of executions.
For example, if you want to execute function f, then g like this:
g(f(x))
It's easier to see the order of executions (e.g., f and then g) this way:
x |> f |> g
Programming languages like OCaml or F# are used a lot to transform data from one form to another, so |> can be used that way to show how data got transformed.
let sqr = x => x * x;
[1,2,3]
|> List.map (x => x + 1)
|> List.map (sqr);
The reverse application operator (|>) can simply be defined as
let (|>) x f = f x
This infix operator takes a value x and a function f and apply the latter to the first (f x). This may not seem apparently useful at first, but the operator is powerful when used correctly because functions in Ocaml are curried.
For example, let's say we had a function wackymath: int -> int -> int -> int
let wackymath a b c = a + b - c
The type of wackymath is int -> int -> int -> int. This is because in a functional realm (specifically, lambda calculus), any function only applies to one argument at a time. Therefore, with the help of parentheses, the order of application of wackymath looks like this:
(((wackymath a) b) c)
Argument substitution could make this clearer.
let f1 = wackymath 10;; (* 10 + b - c *)
let f2 = f1 19;; (* 10 + 19 - c *)
f2 4;; (* 10 + 19 - 4 = 25 *)
This could be expressed with the |> operator as such:
4 |> (19 |> (10 |> wackymath));;
Now it's clear why it's called reverse application operator. The parentheses are there because |> is left-associative. Saying |> helps avoid parentheses are not exactly precise in all cases.
Usually the operator is useful in situations when you want to compose a series of sequential function applications
[1; 2; 3; 4; 5]
|> List.map (fun x -> x * 2)
|> List.filter (fun x -> x < 3)
|> fun l -> match l with
| [] -> 0
| l' -> l' |> List.fold_left ~init:0 ~f:(fun a b -> a + b)
;;
I'am trying to decrypt the return of calc function below but i'am very confused.
I have the f function that takes 3 ints and returns an int.
The calc fuction i think should return val calc : int -> int = <fun> because f has to take 3 ints, i'am giving it x and y so now it needs one more to return another int, the final result. Why it this logic not correct?
I can't make any sense of the actual output, specially with the polymorfic values when i forced parameters in f to be integers.
# let f (x : int) (y : int) (z : int) = x + y + z;;
val f : int -> int -> int -> int = <fun>
# let calc x y f = f x y;;
val calc : 'a -> 'b -> ('a -> 'b -> 'c) -> 'c = <fun>
In the expression let calc x y f = f x y;;, f is a locally-bound variable (calc binds x, y and then f) rather than the function you have defined before.
If you had written let calc x y = f x y;; then you'd have the expected result.
The function calc contains no reference to the functionf. There is an argument named f be it could be named g without changing anything: let calc x y g = g x y. If you want to use the function f you have defined above and not any function of the right type, you must not pass f as an argument, you should rewrite calc like this:
let f x y z = x + y + z
let calc x y = f x y
and then calc will have the type int -> int -> (int -> int) which is more commonly written as int -> int -> int -> int.
I have this statement:
let val x =
let val x = 5
in(fn y =>(y,x+y))
end
in
let val y=3 and z=10
in x z
end
end;
The output is :
(10,15)
I've been trying to track how this answer was produced but am getting confused. Is there a better way to write this that would help me understand what variables are being used where? Thank you!
First, some alpha-conversion:
let val fnPairOfInputAndInputPlus5 =
let val five = 5
in ( fn input => ( input, five + input ) )
end
in let val ignored = 3 and input = 10
in fnPairOfInputAndInputPlus5 input
end
end;
This code is demonstrating that when you declare a function value, unbound values in the declaring scope, such as the value five, are "enclosed" by the declaration (hence the term "closures"). Thus the function always returns a pair consisting of its input and its input plus five.
You could simplify it to
let fun f y = (y,5+y)
val y=3 and z=10
in
f z
end;
Note that the two instances of y are independent. The inner occurrence of x (which I've eliminated) is independent of the outer one (now renamed f).
Can be understood using manual evaluation with detailed explanations.
Starting with your initial expression:
let val x =
let val x = 5
in (fn y => (y,x + y))
end
in
let val y = 3 and z = 10
in x z
end
end;
Line 2,3,4 is an expression whose type is a function, as you see in the in part. It does not depends on any outer context, so it may be simplified as just fn y => (y, 5 + y), substituting x to 5, according to the binding given in let.
So you now have this:
let val x = fn y => (y, 5 + y)
in
let val y = 3 and z = 10
in x z
end
end;
After substitution of x (and removal of the let which in then now not necessary any more):
let val y = 3 and z = 10
in (fn y => (y, 5 + y)) z
end;
Note the y appearing in (y, 5 + y) are bound to the function's argument, and not to 3. There is no reference to this outer y, so its biding may be removed.
Now you have:
let z = 10
in (fn y => (y, 5 + y)) z
end;
Substituting z to 10 and removing the let which is not necessary any more, you get:
(fn y => (y, 5 + y)) 10;
This is a function application. You may evaluate it, to get:
(10, 5 + 10);
Which gives the final and constant result you noticed:
(10, 15);