Is it possible to make this fully polymorphic in OCaml? - functional-programming

in OCaml
let nth_diff_type i (x, y, z) =
match i with
1 -> x
|2 -> y
|3 -> z
|_ -> raise (Invalid_argument "nth")
So the current type is int->('a,'a,'a)->'a, right?
It implies that x, y, z must have the same type.
So my question is that is it possible to give it maximum polymorphic, so that x, y, z don't need to have the same type?

No, it isn't.
A function in OCaml should have only one return type. You can have different argument types if your return type is unique:
let nth_diff_type i (x, y, z) =
match i with
| 1 -> `Fst x
| 2 -> `Snd y
| 3 -> `Thd z
|_ -> raise (Invalid_argument "nth")
// val nth_diff_type :
// int -> 'a * 'b * 'c -> [> `Fst of 'a | `Snd of 'b | `Thd of 'c ] = <fun>
If you would like to create a few utility functions for triplets, unfortunately you have to define them separately:
let fst3 (x, _, _) = x
let snd3 (_, y, _) = y
let thd3 (_, _, z) = z

If your function were to apply an arbitrary function f to an arbitrary element of a tuple such as the function f has the right type, then you could make this polymorphic to some extend.
In other words, if you think about what you may do with your function, you'll come up with the conclusion that you will need a function of the right type to apply it to the result of nth_diff_type, whatever that type may be.
If we suppose for an instant that nth_diff_type works with any tuple, its result is potentially any type. You might get an int, a string, or instances of more complex datatypes. Let's call that type t. Then what can you do with a value of type t? You may only pass it to a function which accepts values of t.
So the problem now is to select the proper function, and that selection certainly will be done on very similar criteria than the rank of the element within your tuple. If it is so, why not simply pass your tuple, and a tuple of the functions which could be applied to nth_diff_type , and let it do the application by itself?
let nth_diff_type i (a,b,c) (fa,fb,fc) =
match i with
| 1 -> fa a
| 2 -> fb b
| 3 -> fc c
| _ -> failwith "out of range"
-: val nth_diff_type : int -> ( 'a * 'b * 'c) -> (('a -> 'd) * ('b -> 'd) * ('c -> 'd)) -> 'd

The code is already fully-polymorphic in non-dependent type systems. You could move to a dependent type system (but you probably don't want, because of the complexity costs), where the type would be something like:
(n : int) -> (a * b * c) -> (match n with 1 -> a | 2 -> b | 3 -> c | _ -> Error)
Besides pad suggestion, you may also want to use a record or object type to have a direct "out projection" operation instead of having to define it by pattern-matching first.
type ('a, 'b, 'c) triple = { nth1 : 'a; nth2 : 'b; nth3 : 'c }
(* replace *) nth_diff_type 2 v (* by *) v.nth2
With an object type (which adds a structural flavor of not having to define the type beforehand)
(* replace *) nth_diff_type 2 v (* by *) v#nth2
Note that these replacement only work with constant integers (because otherwise you need an integer->type dependency). You could work out something with GADTs and existential types to support passing the particular choice around, but you will have to pay a huge complexity cost for something that is more likely a result of not being familiar enough with the existing simple type system to understand how you really want to do things.

Related

Do pure functions have only one possible implementation?

In the image below there is a quick explanation, why pure functions appear to have only one possible implementation.I don't really get the idea because (++) : ('a -> 'b) -> ('a -> 'b) -> 'a -> 'b for example can clearly be implemented by let (++) (f: ('a -> 'b)) (g: ('a -> 'b)) x = f x orlet (++) (f: ('a -> 'b)) (g: ('a -> 'b)) x = g x
Is that image just wrong or do I miss something here?
You are right. The attached image is incorrect even without type annotations.
At first, it's important to consider what kind of "equality" on implementations is assumed here. Let's consider the following examples.
Is (##) equal to (##+)?
let ( ## ) f x = f x
let ( ##+ ) f x =
let _ = 42 in
f x
Is (|>) equal to (|>+)?
let ( |> ) x f = f x
let ( |>+ ) x f = f ## x
Is (%) equal to (%+)?
let ( % ) f g x = f (g x)
let ( %+ ) p q r = p (q r)
If (##) is not equal to (##+), then we can construct the 5th implementation of a function bool -> bool, such as (fun x -> let _ = 42 in true).
Therefore, the author of the image would have wanted to distinguish functions not by its implementation (or codes), but by some other element such as its behavior (like duck test or the equality on mathematical functions).
Still, the image is incorrect. The image claims "for pure functions that don't have any concrete type in the signature, there is only one possible implementation", but no. For example, there is no pure function 'a -> 'b. This can be shown through the Curry–Howard correspondence.
The image is wrong if you consider the counterexample you just gave. I think the author of the image didn’t consider the possibility of type annotation.
In fact if
there are no type annotations and
all the arguments are polymorphic and or function over polymorphic types,
you don’t consider the existence of polymorphic operators such as = or <>
(otherwise it is wrong since <> and = have the same type and different implementation),
then there is only one pure implementation of your function signature.
(you can probably prove that by saying the only things you can use to define that function are :
pure functions of the same type, that can be inlined, so you can ignore that
match-patterns and let, for which the image’s argument is true
cartesian product (let f a b = a, b)
function composition
infinite recursion
and maybe other things I forget, but you can make an exhaustive list
and that the combination of these used can be guessed from the output and input types.
)

Converting a binary tree to a list using fold function in Ocaml

Given:
type 'a tree = Empty | Node of 'a * 'a tree * 'a tree
Use:
let rec tree_fold f e t = match t with
| Empty -> e
| Node (x, l, r) -> f x (tree_fold f e l) (tree_fold f e r);;
to convert a binary tree to a list.
Example.
let someTree = Node (1,Node(2,Node(3,Empty,Empty),Empty),Empty)
tree2list someTree gives [1;2;3].
My attempt:
let tree2list tr = match tr with
| Empty -> Empty
| Node (x,l,r) -> (tree_fold (fun acc tree-> tree::acc) [] tr)
It gives the error:
This expression has type 'a list but an expression was expected of type 'b -> 'b .
I've been at this for hours and keep getting similar errors. Any help would be very appreciated, even just a small hint would be great.
Thanks.
function that you should pass to a tree_fold accepts three arguments, and you're passing a function that can take only two arguments. That's what compiler tries to say. Of course, ther're some other problems, but I hope tha you'll cope with them!

Write a function with different return types in OCaml

How can I re-write this function in OCaml so that it allows the elements of the tuple to have different types
let nth i (x,y,z) =
match i with
1->x
|2->y
|3->z
|_->raise (Invalid_argument "nth")
The short answer is that it's not possible. OCaml is strongly and statically typed. A function returns a single type. Since your function returns x, y, and z in different cases, then these must all be the same type.
OCaml types are not like types in the so-called dynamically typed languages. You need to think differently. The benefits are (in my opinion) tremendous.
It can be done, but you need to fulfill the constraint that all values, returned from the function should be members of one type. The easiest solution is:
let nth i (x,y,z) =
match i with
| 1 -> `Fst x
| 2 -> `Snd y
| 3 -> `Thd z
| _ -> invalid_arg "nth tuple"
The solution demonstrates that you need to address all possible cases for the types of your tuple. Otherwise, your program will not be well-formed, and this contradicts with the static typing. The latter guarantees that your program is well-formed for any input, so that it wont fail in a runtime.
A twin solution, using ordinary ADT instead of polymorphic ones, will look something like this:
type ('a,'b,'c) t =
| Fst of 'a
| Snd of 'b
| Thd of 'c
let nth i (x,y,z) =
match i with
| 1 -> Fst x
| 2 -> Snd y
| 3 -> Thd z
| _ -> invalid_arg "nth tuple"
An exotic solution (not very practible, maybe) that uses GADT to form an existential type will look like this:
type t = Dyn : 'a -> t
let nth i (x,y,z) =
match i with
| 1 -> Dyn x
| 2 -> Dyn y
| 3 -> Dyn z
| _ -> invalid_arg "nth tuple"

signatures/types in functional programming (OCaml)

I started learning functional programming (OCaml), but I don't understand one important topic about fp: signatures (I'm not sure if it's a proper name). When I type something and compile with ocaml, I get for example:
# let inc x = x + 1 ;;
val inc : int -> int = <fun>
This is trivial, but I don't know, why this:
let something f g a b = f a (g a b)
gives an output:
val something : (’a -> ’b -> ’c) -> (’a -> ’d -> ’b) -> ’a -> ’d -> ’c = <fun>
I suppose, that this topic is absolutely basics of fp for many of you, but I ask for help here, because I haven't found anything on the Internet about signatures in OCaml (there are some articles about signatures in Haskell, but not explanations).
If this topic somehow will survive, I post here several functions, which signatures made me confused:
# let nie f a b = f b a ;; (* flip *)
val nie : (’a -> ’b -> ’c) -> ’b -> ’a -> ’c = <fun>
# let i f g a b = f (g a b) b ;;
val i : (’a -> ’b -> ’c) -> (’d -> ’b -> ’a) -> ’d -> ’b -> ’c = <fun>
# let s x y z = x z (y z) ;;
val s : (’a -> ’b -> ’c) -> (’a -> ’b) -> ’a -> ’c = <fun>
# let callCC f k = f (fun c d -> k c) k ;;
val callCC : ((’a -> ’b -> ’c) -> (’a -> ’c) -> ’d) -> (’a -> ’c) -> ’d = <fun>
Thank you for help and explanation.
There are a couple of concepts you need to understand to make sense of this type signature and I don't know which ones you already do, so I tried my best to explain every important concept:
Currying
As you know, if you have the type foo -> bar, this describes a function taking an argument of type foo and returning a result of type bar. Since -> is right associative, the type foo -> bar -> baz is the same as foo -> (bar -> baz) and thus describes a function taking an argument of type foo and returning a value of type bar -> baz, which means the return value is a function taking a value of type bar and returning a value of type baz.
Such a function can be called like my_function my_foo my_bar, which because function application is left-associative, is the same as (my_function my_foo) my_bar, i.e. it applies my_function to the argument my_foo and then applies the function that is returned as a result to the argument my_bar.
Because it can be called like this, a function of type foo -> bar -> baz is often called "a function taking two arguments" and I will do so in the rest of this answer.
Type variables
If you define a function like let f x = x, it will have the type 'a -> 'a. But 'a isn't actually a type defined anywhere in the OCaml standard library, so what is it?
Any type that starts with a ' is a so-called type variable. A type variable can stand for any possible type. So in the example above f can be called with an int or a string or a list or anything at all - it doesn't matter.
Furthermore if the same type variable appears in a type signature more than once, it will stand for the same type. So in the example above that means, that the return type of f is the same as the argument type. So if f is called with an int, it returns an int. If it is called with a string, it returns a string and so on.
So a function of type 'a -> 'b -> 'a could take two arguments of any types (which might not be the same type for the first and second argument) and returns a value of the same type as the first argument, while a function of type 'a -> 'a -> 'a would take two arguments of the same type.
One note about type inference: Unless you explicitly give a function a type signature, OCaml will always infer the most general type possible for you. So unless a function uses any operations that only work with a given type (like + for example), the inferred type will contain type variables.
Now to explain the type...
val something : ('a -> 'b -> 'c) -> ('a -> 'd -> 'b) -> 'a -> 'd -> 'c = <fun>
This type signature tells you that something is a function taking four arguments.
The type of the first argument is 'a -> 'b -> 'c. I.e. a function taking two arguments of arbitrary and possibly different types and returning a value of an arbitrary type.
The type of the second argument is 'a -> 'd -> 'b. This is again a function with two arguments. The important thing to note here is that the first argument of the function must have the same type as the first argument of the first function and the return value of the function must have the same type as the second argument of the first function.
The type of the third argument is 'a, which is also the type of the first arguments of both functions.
Lastly, the type of the fourth argument is 'd, which is the type of the second argument of the second function.
The return value will be of type 'c, i.e. the return type of the first function.
If you're really interested in the subject (and have access to a university library), read Wadler's excellent (if somewhat dated) "Introduction to functional programming". It explains type signatures and type inference in a very nice and readable way.
Two further hints: Note that the -> arrow is right-associative, so you can bracket things from the right which sometimes helps to understand things, ie a -> b -> c is the same as a -> (b -> c). This is connected to the second hint: Higher order functions. You can do things like
let add x y = x + y
let inc = add 1
so in FP, thinking of 'add' as a function that has to take two numerical parameters and returns a numerical value is not generally the right thing to do: It can also be a function that takes one numerical argument and returns a function with type num -> num.
Understanding this will help you understand type signatures, but you can do it without. Here, quick and easy:
# let s x y z = x z (y z) ;;
val s : (’a -> ’b -> ’c) -> (’a -> ’b) -> ’a -> ’c = <fun>
Look at the right hand side. y is given one argument, so it is of type a -> b where a is the type of z. x is given two arguments, the first one of which is z, so the type of the first argument has to be a as well. The type of (y z) , the second argument, is b, and hence the type of x is (a -> b -> c). This allows you to deduce the type of s immediately.

OCaml: Is there a function with type 'a -> 'a other than the identity function?

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.

Resources