I want to implement a (simple) mathematical function addition in F#, meaning:
Imagine F being the field of all functions, which map an element of A to an element of B:
Then, my "function addition" should be defined as follows:
I have tried the following code to implement the function addition as the operator !+:
let inline (!+) (f1 : ^a -> ^b, f2 : ^a -> ^b) : ^a -> ^b =
let f (x : ^a) : ^b =
(f1 x) + (f2 x)
f
However, if I want to compile the following lines, I will get an error:
let f1 x : float = -x // negate x
let f2 x : float = 2. * x // multiply by 2
let f3 = f1 !+ f2 //error : Expexceted `float`, got `'a -> 'b`
I am pretty sure, that it is caused by some simple logical error, but I was yet unable to find it.
My question therefore is: How does one define a function addition in F#?
Quite close !
Two main issues:
!+ is a unary operator. See the rules for F# operators.
your function is taking tuples. It's not curried.
Correct it and you get it working:
let inline (++) (f1 : ^a -> ^b) (f2 : ^a -> ^b) : ^a -> ^b =
let f (x : ^a) : ^b =
(f1 x) + (f2 x)
f
let f1 x : float = -x
let f2 x : float = 2. * x
let f3 = f1 ++ f2
Let me add that you don't need any type annotation, F# will figure it out for you:
let inline (++) f1 f2 x = f1 x + f2 x
If you read the signature you'll notice that your functions can have any input type, just the result types should match:
let inline f1 x = -(float x)
let f2 x : float = float (2 * x)
let f3 = f1 ++ f2
Related
I have the following code written in Ocaml to try and generate the first 50 catalan numbers:
let rec f n:int64=
if n<1 then 1L
else (4*n-2)*f((n-1L))/(n+1L)
;;
for i = 0 to 50 do
Printf.printf "%d\n"(f i)
done;
But the problem is that the recursion function doesn't seem to accept Int64 values and seems to want Int instead despite me notating n as int64:
File "/proc/self/fd/0", line 3, characters 19-21:
3 | else (4*n-2)*f((n-1L))/(n+1L)
^^
Error: This expression has type int64 but an expression was expected of type
int
exit status 2
Is there a way to ensure I can int64 numbers here with recursion?
Your problem isn't recursion per se, it's that the operators in OCaml are strongly typed. So the - operator is of type int -> int -> int.
Without getting into lots of fussing with the syntax, the easiest fix is probably to use the named functions of the Int64 module. You can use Int64.sub rather than -, for example.
You can use the notation Int64.(... <expr> ...) to avoid repeating the module name. If you rewrite your code this way, you get something like this:
let rec f (n : int64) : int64 =
Int64.(
if n < 1L then 1L
else
mul (sub (mul 4L n) 2L)
(f (div (sub n 1L) (add n 1L)))
)
Looking at the results computed by this function, they don't look like Catalan numbers to me. In fact the 50th Catalan number is too large to be represented as an int64 value.
So there is still some work to do. But this is how to get past the problem you're seeing (IMHO).
If you really want to work with such large numbers, you probably want to look at the Zarith module.
Submitted as an additional suggestion to Jeffrey's answer: whether using Int64 or Zarith, you might create a module defining arithmetic operators and then locally open that to clean up your code.
E.g.
module Int64Ops =
struct
let ( + ) = Int64.add
let ( - ) = Int64.sub
let ( * ) = Int64.mul
let ( / ) = Int64.div
end
let rec f n =
Int64Ops.(
if n < 1L then 1L
else (4L * n - 2L) * f (n - 1L) / (n + 1L)
)
Or you could use a functor to make it easier to work with multiple different types of numbers.
module type S =
sig
type t
val add : t -> t -> t
val sub : t -> t -> t
val mul : t -> t -> t
val div : t -> t -> t
end
module BasicArithmeticOps (X : S) =
struct
type t = X.t
let ( + ) = X.add
let ( - ) = X.sub
let ( * ) = X.mul
let ( / ) = X.div
end
# let module A = BasicArithmeticOps (Float) in
A.(8. + 5.1);;
- : float = 13.1
# let module A = BasicArithmeticOps (Int) in
A.(8 + 3);;
- : int = 11
# let module A = BasicArithmeticOps (Int64) in
A.(4L + 3L);;
- : int64 = 7L
My julia version is 1.7.1.
These code can recurrent my problem:
struct Foo1
sixsix
aa
bb
disposion
end
struct Foo2
aa
bb
end
function Base.:+(f1::Foo1, f2 :: Foo2)
newf = f1
for n in fieldnames(typeof(f2))
getproperty(newf, n) += getproperty(f2, n)
end
return newf
end
returned LoadError: syntax: invalid assignment location "getproperty(newf, n)"
same LoadError happened when I try to use getfield:
function Base.:+(f1::Foo1, f2 :: Foo2)
newf = f1
for n in fieldnames(typeof(f2))
getfield(newf, n) += getfield(f2, n)
end
return newf
end
Firstly, you must make your structs mutable for this to work.
Secondly, this:
getproperty(newf, n) += getproperty(f2, n)
is expanded into
getproperty(newf, n) = getproperty(newf, n) + getproperty(f2, n)
In other words you are apparently trying to assign a value into a function call. In Julia you can only assign to variables, not to values. The only thing this syntax is allowed for is function definition. From the manual:
There is a second, more terse syntax for defining a function in Julia.
The traditional function declaration syntax demonstrated above is
equivalent to the following compact "assignment form":
julia> f(x,y) = x + y
f (generic function with 1 method)
So the syntax you are using doesn't do what you want, and what you want to do is not possible anyway, since you can only assign to variables, not to values.
What you are trying to do can be achieved like this (assuming n is a Symbol):
setfield!(newf, n, getfield(newf, n) + getfield(f2, n))
I would rather recommend you to do the following:
Base.:+(f1::Foo1, f2 :: Foo2) =
Foo1(f1.sixsix, f1.aa+f2.aa, f1.bb+f2.bb, f1.disposion)
Your code is wrong for the following reasons:
Foo1 is not mutable, so you cannot change values of its elements
to set a field of mutable struct (which your struct is not) you use setfield!
You mix properties and fields of a struct which are not the same.
fieldnames works on types not on instances of type.
If you wanted to be more fancy and do automatic detection of matching fields you could do:
Base.:+(f1::Foo1, f2 :: Foo2) =
Foo1((n in fieldnames(Foo2) ?
getfield(f1, n) + getfield(f2, n) :
getfield(f1, n) for n in fieldnames(Foo1))...)
However, I would not recommend it, as I feel that it is overly complicated.
This is the code I tried
fun printsl([], k) = true
| printsl(h::t) = if k > h then print(h) andalso printsl(t);
But when I run the code, i get the following error
= stdIn:4.68-7.8 Error: syntax error: deleting SEMICOLON ID
stdIn:8.1 Error: syntax error found at EOF
The goal of the function is to print any number in the list that is less than the value k
A few things wrong here. Let's start with your function signature.
On the first line, your function takes 2 parameters, an empty list and whatever the type of k is (it is not important yet). Then on the second line, the function takes just one parameter, a non-empty list.
The two lines should match to look like:
fun printsl([], k) = ...
| printsl(h::t, k) = ...
Now let's think about the use of andalso. andalso is an operator which takes two booleans and returns a bool. It can be considered to have the signature bool * bool -> bool.
Your usage print(h) andalso printsl(t) does not match this signature.
The type of print is string -> unit, so the type of print(h) is unit (assuming h to be a string). As such, the usage of andalso is incorrect as the types on each side are not bools.
Instead of using andalso, we can simply execute both statements (print(h); printsl(t, k)). Sequences like this are expressions which return the last value. That is to say (x; y; z) returns z.
fun printsl([], k) = true
| printsl(h::t, k) = if h < k then (print(h); printsl(t, k));
However, this is still broken as the if-else construct in SML is an expression and must have a matching else, so you could use either of the following:
fun printsl([], k) = true
| printsl(h::t, k) =
if h < k then (print(h); printsl(t))
else printsl(t, k);
fun printsl([], k) = true
| printsl(h::t, k) = (
if h < k then print(h) else ();
printsl(t, k)
);
I personally prefer the latter as it prevents repetition of printsl.
This code will compile, but the signature is wrong. As we use h directly as a parameter of print, its type is inferred to be a string. This means that the compiler determines printsl to have type string list * string -> bool, whereas we are aiming for int list * int -> bool.
This can be corrected by changing the call print(h) to print(Int.toString h), giving us:
fun printsl([], k) = true
| printsl(h::t, k) = (
if h < k then print(Int.toString h) else ();
printsl(t, k)
);
This is now a function which will print all values in the given list which are less than k, but it always returns true. This provides no extra information so I would be inclined to change the signature to int list * int -> unit, giving us (finally):
fun printsl([], k) = ()
| printsl(h::t, k) = (
if h < k then print(Int.toString h) else ();
printsl(t, k)
);
This entire program could also be written in a more functional manner using List.app and List.filter.
fun printsl (xs, k) =
List.app
(fn y => print (Int.toString y))
(List.filter
(fn x => x < k)
xs);
Suppose a function g is defined as follows.
utop # let g ~y ~x = x + y ;;
val g : y:int -> x:int -> int = <fun>
utop # g ~x:1 ;;
- : y:int -> int = <fun>
utop # g ~y:2 ;;
- : x:int -> int = <fun>
utop # g ~x:1 ~y:2 ;;
- : int = 3
utop # g ~y:2 ~x:1 ;;
- : int = 3
Now there is another function foo
utop # let foobar (f: x:int -> y:int -> int) = f ~x:1 ~y:2 ;;
val foobar : (x:int -> y:int -> int) -> int = <fun>
Sadly when I try to provide g as the parameter of foobar, it complains:
utop # foobar g ;;
Error: This expression has type y:int -> x:int -> int
but an expression was expected of type x:int -> y:int -> int
This is quite surprising as I can successfully currify g but cannot pass it as the parameter. I googled and found this article which doesn't help much. I guess this is related to the underlying type system of OCaml (e.g. subtyping rules of labeled arrow types).
So is it possible to pass g as the parameter to foobar by any means in OCaml? If not, why is it not allowed? Any supporting articles/books/papers would be sufficient.
The key is that labels do not exist at runtime. A function of type X:int -> y:float -> int is really a function whose first argument is an int and whose second argument is a float.
Calling g ~y:123 means that we store the second argument 123 somewhere (in a closure) and we will use it automatically later when the original function g is finally called with all its arguments.
Now consider a higher-order function such as foobar:
let foobar (f : y:float -> x:int -> int) = f ~x:1 ~y:2.
(* which is the same as: *)
let foobar (f : y:float -> x:int -> int) = f 2. 1
The function f passed to foobar takes two arguments, and the float must be the first argument, at runtime.
Maybe it would be possible to support your wish, but it would add some overhead. In order for the following to work:
let g ~x ~y = x + truncate y;;
foobar g (* rejected *)
the compiler would have to create an extra closure. Instead you are required to do it yourself, as follows:
let g ~x ~y = x + truncate y;;
foobar (fun ~y ~x -> g ~x ~y)
In general, the OCaml compiler is very straightforward and won't perform this kind of hard-to-guess code insertion for you.
(I'm not a type theorist either)
Think instead of the types x:int -> y:float -> int and y:float -> x:int -> int. I claim these are not the same type because you can call them without labels if you like. When you do this, the first requires an int as its first parameter and a float as the second. The second type requires them in the reverse order.
# let f ~x ~y = x + int_of_float y;;
val f : x:int -> y:float -> int = <fun>
# f 3 2.5;;
- : int = 5
# f 2.5 3;;
Error: This expression has type float but an expression was
expected of type int
Another complication is that functions can have some labelled and some unlabelled parameters.
As a result, the labeled parameters of a function are treated as a sequence (in a particular order) rather than a set (without an inherent order).
Possibly if you required all parameters to be labelled and removed the capability of calling without labels, you could make things work the way you expect.
(Disclaimer: I'm not a type theorist, though I wish I was.)
This pitfall of labels in OCaml is described in detail in the Labels and type inference subsection of the OCaml manual, giving an example similar to yours.
If I remember correctly, some type systems for labels lift that restriction, but at the cost of additional overall complexity that was judged "not worth it" for the OCaml language itself. Labels can be rearranged automatically at first-order application sites, but not when abstracting over labelled functions (or using such abstractions).
You can have your example accepted by manually eta-expanding the labelled function to make a reorderable application appear (a type-theorist would say this is a retyping eta-conversion):
# let f ~x ~y = x+y;;
val f : x:int -> y:int -> int = <fun>
# let yx f = f ~y:0 ~x:1;;
val yx : (y:int -> x:int -> 'a) -> 'a = <fun>
# yx f;;
Error: This expression has type x:int -> y:int -> int
but an expression was expected of type y:int -> x:int -> 'a
# yx (fun ~y ~x -> f ~y ~x);;
- : int = 1
This isn't a homework question, by the way. It got brought up in class but my teacher couldn't think of any. Thanks.
How do you define the identity functions ? If you're only considering the syntax, there are different identity functions, which all have the correct type:
let f x = x
let f2 x = (fun y -> y) x
let f3 x = (fun y -> y) (fun y -> y) x
let f4 x = (fun y -> (fun y -> y) y) x
let f5 x = (fun y z -> z) x x
let f6 x = if false then x else x
There are even weirder functions:
let f7 x = if Random.bool() then x else x
let f8 x = if Sys.argv < 5 then x else x
If you restrict yourself to a pure subset of OCaml (which rules out f7 and f8), all the functions you can build verify an observational equation that ensures, in a sense, that what they compute is the identity : for all value f : 'a -> 'a, we have that f x = x
This equation does not depend on the specific function, it is uniquely determined by the type. There are several theorems (framed in different contexts) that formalize the informal idea that "a polymorphic function can't change a parameter of polymorphic type, only pass it around". See for example the paper of Philip Wadler, Theorems for free!.
The nice thing with those theorems is that they don't only apply to the 'a -> 'a case, which is not so interesting. You can get a theorem out of the ('a -> 'a -> bool) -> 'a list -> 'a list type of a sorting function, which says that its application commutes with the mapping of a monotonous function.
More formally, if you have any function s with such a type, then for all types u, v, functions cmp_u : u -> u -> bool, cmp_v : v -> v -> bool, f : u -> v, and list li : u list, and if cmp_u u u' implies cmp_v (f u) (f u') (f is monotonous), you have :
map f (s cmp_u li) = s cmp_v (map f li)
This is indeed true when s is exactly a sorting function, but I find it impressive to be able to prove that it is true of any function s with the same type.
Once you allow non-termination, either by diverging (looping indefinitely, as with the let rec f x = f x function given above), or by raising exceptions, of course you can have anything : you can build a function of type 'a -> 'b, and types don't mean anything anymore. Using Obj.magic : 'a -> 'b has the same effect.
There are saner ways to lose the equivalence to identity : you could work inside a non-empty environment, with predefined values accessible from the function. Consider for example the following function :
let counter = ref 0
let f x = incr counter; x
You still that the property that for all x, f x = x : if you only consider the return value, your function still behaves as the identity. But once you consider side-effects, you're not equivalent to the (side-effect-free) identity anymore : if I know counter, I can write a separating function that returns true when given this function f, and would return false for pure identity functions.
let separate g =
let before = !counter in
g ();
!counter = before + 1
If counter is hidden (for example by a module signature, or simply let f = let counter = ... in fun x -> ...), and no other function can observe it, then we again can't distinguish f and the pure identity functions. So the story is much more subtle in presence of local state.
let rec f x = f (f x)
This function never terminates, but it does have type 'a -> 'a.
If we only allow total functions, the question becomes more interesting. Without using evil tricks, it's not possible to write a total function of type 'a -> 'a, but evil tricks are fun so:
let f (x:'a):'a = Obj.magic 42
Obj.magic is an evil abomination of type 'a -> 'b which allows all kinds of shenanigans to circumvent the type system.
On second thought that one isn't total either because it will crash when used with boxed types.
So the real answer is: the identity function is the only total function of type 'a -> 'a.
Throwing an exception can also give you an 'a -> 'a type:
# let f (x:'a) : 'a = raise (Failure "aaa");;
val f : 'a -> 'a = <fun>
If you restrict yourself to a "reasonable" strongly normalizing typed λ-calculus, there is a single function of type ∀α α→α, which is the identity function. You can prove it by examining the possible normal forms of a term of this type.
Philip Wadler's 1989 article "Theorems for Free" explains how functions having polymorphic types necessarily satisfy certain theorems (e.g. a map-like function commutes with composition).
There are however some nonintuitive issues when one deals with much polymorphism. For instance, there is a standard trick for encoding inductive types and recursion with impredicative polymorphism, by representing an inductive object (e.g. a list) using its recursor function. In some cases, there are terms belonging to the type of the recursor function that are not recursor functions; there is an example in §4.3.1 of Christine Paulin's PhD thesis.