OCaml polymorphism example other than template function? - c++

I am trying to understand for myself, which form of polymorhism does OCaml language have.
I was provided by an example
let id x = x
Isn't this example equivalent to C++ template function
template<class A> A id(A x) { return x; }
If so then my question is: are there any other forms of polymorphism in OCaml? This notion is called "generic algorithm" in the world of imperative languages, not "polymorphism".

There are basically three language features that are sometimes called polymorphism:
Parametric polymorphism (i.e. "generics")
Subtype polymorphism, this is the ability of a subtype of a type to offer a more specific version of an operation than the supertype, i.e. the ability to override methods (and the ability of the the runtime system to call the correct implementation of a method based on the runtime type of an object). In OO languages this is often simply referred to as "polymorphism".
So-called ad-hoc polymorphism, i.e. the ability to overload functions/methods.
As you already discovered, OCaml has parametric polymorphism. It also has subtype polymorphism. It does not have ad-hoc polymorphism.
Since in your title you've asked for examples, here's an example of subtype polymorphism in OCaml:
class c = object
method m x = x+1
end
class d = object
inherit c
method m x = x+2
end
let main =
let o:c = new d in
print_int (o#m 2)
This will print 4.

This kind of polymorphism is called generic programming but the theoretical concept behind it is called parametric polymorphism.
The two examples you provided indeed show parametric polymorphism but OCaml is supported by a strong inferring type checker instead that the one provided by C++ (which is a solution more pragmatic and with more caveats) so the real difference is that in C++ the code is duplicated for every type you use it in your code while in OCaml it is resolved by type checker by verifying that a substitution of implicit type variables through unification does exist.
Everything can be polymorphic in OCaml just because nothing is usually annotated with types so in practice if something can be used as an argument to any function then it is implicitly allowed.
You can for example have type variables to define polymorphic methods:
let swap ((x : 'a), (y : 'b)) : 'b * 'a = (y, x)
so that this will work whatever type 'a o 'b is.
Another powerful polymorphic feature of OCaml are functors (which are not the common C++ functors) but are modules parametrized by other modules. The concept sounds scarier that it is but they indeed represent an higher order of polymorphic behavior for OCaml code.

Related

Is it possible to support higher-kinded types in Standard ML?

I have read in this post that ML dialects do not allow type variables of non-ground kind. E.g. the last statement is not representable:
-- Haskell code
type Ground = Int
type FirstOrder a = Maybe a
type SecondOrder c = c Int -- ML do not allow :c
OCaml has support of higher-kinded only at the level of modules. There are some explanations (here and author's comment here) about which features of OCaml clash with higher-kinded types opportunity.
If I understood it correctly, the main problem is in the following facts:
OCaml does not follow a "freshness" restriction for type definitions: construct type can define both an alias (an the type will remain the same) and a new fresh type
type alias definition can be hidden
AFAIK, Standard ML has different constructs for type definition and aliases: type for aliases and datatype for new fresh types introduction.
Unfortunatelly, I do not know SML well enough -- is it possible to export type aliases with its definition hidden? And can someone please show me if there are any other SML features that still do not go well with an opportunity of higher-kinded types?
Probably there will be some problems with functors -- Could one be so kind to show a code example of it? I've heard several times about such cases but still have not found a complete example of it.
Yes, SML can express the equivalent of higher-kinded types through functors, and can also make them abstract. Useless example:
functor F (type 'a t) :> sig type 'a u end =
struct
type 'a u = ('a t) t
end
However, unlike OCaml, SML does not (officially) have higher-order functors, so per the standard, you can only express second-order type constructors this way.
FWIW, OCaml may use the same keyword for type aliases and generative types (type vs datatype in SML), but they are still distinguished syntactically, by their right-hand side. So that's no real difference to SML.In both languages, an abstract occurring in a signature can be implemented as either a type alias or a generative type. So the problem for type inference that Leo is alluding to exists equally in both. Haskell can get away without that problem because it does not have the same expressiveness regarding type abstraction (i.e., no "sealing" operator for modules).

Faking Return value with F# and FakeItEasy

I am trying to use FakeItEasy to mock an interface defined in C#
public interface IMyInterface
{
int HeartbeatInterval { get; set; }
}
In the F# test i do
let myFake = A.Fake<IMyInterface>()
A.CallTo(fun () -> ((!myFake).HeartbeatInterval)).Returns(10) |> ignore
Running this in the test runner results in
System.ArgumentException
Expression of type 'Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Int32]' cannot be used for return type 'System.Int32'
In fact it would seem that it does this for any return type e.g. if HeartbeatInterval returned type of foo then the exception thrown would be for type foo instead of System.Int32.
Am i doing this wrong or is there some incompatibility between F# and FakeItEasy?
It has crossed my mind that using an Object Expression might be an easier way to go.
I would venture a hypothesis that the "Easy" in "FakeItEasy" stands for "Easy Over Simple". The library says it's "easy", and that is probably true if you're using it from C#. Because it is quite obviously designed for use with that language. But it is far from "simple", because it is using C#-specific syntactic tricks that are hidden from view and don't work in F# well.
The specific gotcha you're getting right now is a combination of two things: (1) F# functions are not the same as C# Func<T,R>, and (2) F# overload resolution rules are different from C#.
There are three overloads of CallTo - two of them take an Expression<_>, and the third one is a "catch-all", taking an object. In C#, if you call this method with a lambda-expression as argument, the compiler will try its best to convert the lambda-expression to an Expression<_> and call one of the specialized methods. F#, however, does not make this effort: F#'s support for C#-style Expression<_> is very limited, primarily focused on compatability with LINQ, and only kicks in when there are no alternatives. So in this case, F# chooses to call the CallTo(object) overload.
Next, what would the argument be? F# is a very strict and consistent language. Apart from some special interop cases, most F# expressions have a definite type, regardless of the context in which they appear. Specifically, an expression of the form fun() -> x will have type unit -> 'a, where 'a is the type of x. In other words, it's an F# function.
At runtime, F# functions are represented by the type FSharpFunc<T,R>, so that is what the compiler will pass to the CallTo(object) method, which will look at it and, unable to understand what the hell it is, throw an exception.
To fix it, you could make yourself a special version of CallTo (let's call it FsCallTo) that would force the F# compiler to convert your fun() -> x expression into an Expression<_>, then use that method instead of CallTo:
// WARNING: unverified code. Should work, but I haven't checked.
type A with
// This is how you declare extension methods in F#
static member FsCallTo( e: System.Linq.Expressions.Expression<System.Func<_,_>> ) = A.CallTo( e )
let myFake = A.Fake<IMyInterface>()
// Calling FsCallTo will force F# to generate an `Expression<_>`,
// because that's what the method expects:
A.FsCallTo(fun () -> ((!myFake).HeartbeatInterval)).Returns(10) |> ignore
However, as you have absolutely correctly observed, this is way too much of a hassle for mocking up an interface, since F# already has a perfectly statically verifiable, runtime-cost-free, syntactically nice alternative in the form of object expressions:
let myFake = { new IMyInterface with
member this.HeartbeatInterval = 10
member this.HeartbeatInterval with set _ = ()
}
I would totally recommend going with them instead.

Why is C++ said not to support parametric polymorphism?

According to the wikipedia page for Parametric Polymorphism:
Some implementations of type polymorphism are superficially similar to parametric polymorphism while also introducing ad hoc aspects. One example is C++ template specialization.
Question: Why is C++ said to only implement something superficially similar to paramaterized polymorphism? In particular, aren't templates an example of full on parametric polymorphism?
The article you linked to explains that. The very text you quoted actually gives one example of something that sets C++'s templates apart from pure parametric polymorphism: C++ template specialisation.
It continues on this theme:
Following Christopher Strachey,[2] parametric polymorphism may be contrasted with ad hoc polymorphism, in which a single polymorphic function can have a number of distinct and potentially heterogeneous implementations depending on the type of argument(s) to which it is applied. Thus, ad hoc polymorphism can generally only support a limited number of such distinct types, since a separate implementation has to be provided for each type.
Thus, as described, C++ templates come close to — but are not exactly — parametric polymorphism.
Why is C++ said to only implement something superficially similar to parameterized polymorphism? In particular, aren't templates an example of full on parametric polymorphism?
Templated functions in C++ work on the basis of "substitution" of the parameter. Which essentially means that the compiler generates yet another version of the function where the template arguments are hardcoded into the function.
Suppose you have this in C++:
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
int i = add(2, 3);
double d = add(2.7, 3.8);
return i + (int)d;
}
During compilation, that will result in two functions: int add(int a, int b) { return a + b; } and double add(double a, double b) { return a + b; }
One function will ONLY handle ints, and the other will ONLY handle doubles. No polymorphism.
So really, you end up with as many implementations as the number of argument variations.
"But why isn't this parametric polymorphism?" you might ask?
You need the full source code of the 'add' function, in order to call it with your own particular variation of something that overloads the binary '+' operator! - That's the detail that makes the difference.
If C++ had proper parametric polymorphism, like C# for instance, your final compiled implementation of 'add' would contain enough logic to determine at runtime what the '+' overload would be for any given parameter acceptable to 'add'. And you wouldn't need the source code for that function, to call it with new types you invented.
What does this mean in reality?
But don't understand this as if C++ is less powerful or C# being more powerful. It's simply one of many language feature details.
If you have the full source available for your templated functions, then C++'s semantics are far superior. If you only have a static or dynamic library at your disposal, then a parametric polymorphic implementation (e.g. C#) is superior.

why does OCaml use subtyping for polymorphic variants?

I have just read about row polymorphism and how it can be used for extensible records and polymorphic variants.
However, Ocaml uses subtyping for polymorphic variants. Why? Is it more powerful than row polymorphism?
OCaml uses both row polymoprhism and subtyping for polymorphic variants (and objects, for that matter). Row polymorphism is involved for "open" object types < m1 : t1; m2 : t2; .. > (the .. being literally part of the type), or "open" variant types [> `K1 of t1 | `K2 of t2 ]. Subtyping is used to be able to cast between closed, non-polymorphic types <m1:t1; m2:t2> :> <m1:t1> or [ `K1 of t1 ] :> [ `K1 of t1 | `K2 of t2 ].
Row polymorphism allows to avoid the need for bounded quantification to express types such as "take an object that has at least the method m, and return an object of the same type": subtyping is therefore rather simple, explicit, and cannot be abstracted over. On the contrary, row polymorphism is easier to infer and will play better with the rest of the type system. It should be rarely necessary to use closed types and explicit subtyping, but that is occasionally convenient -- and in particular, keeping type closed can produce error messages that are easier to understand.
To complement Gabriel's answer, one way to think about this is that subtyping provides a weak form of both universal and existential polymorphism. When both directions of parametric polymorphism are available, then the expressiveness of subtyping is mostly subsumed (especially when there is no depth subtyping). But that's not the case in Ocaml.
Ocaml replaces the universal aspect by actual universal polymorphism, but keeps subtyping to give you a form of existential quantification that it otherwise doesn't have. That is needed to form e.g. heterogeneous collections, such as a <a: int> list in which you want to be able to store arbitrary objects that at least have an a method of the right type.
I would go even further and say that, while this is usually explained as subtyping in the Ocaml world, you could actually interpret closed rows as existentially quantified over an (unknown) tail. Coercion via :> would then be existential introduction, thereby staying more faithful to the world of parametric polymorphism that rows are built upon. (Of course, under this interpretation, # would do implicit existential elimination.) If I were to design an Ocaml-like system from scratch, I'd probably try to model it that way.

What's the difference (if any) between Standard ML's module system and OCaml module system?

My question is if there is any difference between Standard ML's module system and OCaml module system? Has OCaml all the support of functors , ascriptions etc... that SML has?
There are some differences feature-wise, as well as semantically.
Features SML supports but not OCaml:
transparent signature ascription
module-level let
symmetric sharing constraints
syntactic sugar for functors over types and values
Features OCaml 4 has but not SML:
higher-order functors
recursive modules
local modules
nested signatures
modules as first-class values
general module sharing (sig with module A = M)
module type of
Several SML implementations provide some of these as extensions, however: e.g. higher-order functors (SML/NJ, Moscow ML, Alice ML), local and first-class modules (Moscow ML, Alice ML), module sharing (SML/NJ, Alice ML), nested signatures (Moscow ML, Alice ML), and recursive modules (Moscow ML).
Semantics-wise, the biggest difference is in the treatment of type equivalence, especially with respect to functors:
In SML, functors are generative, which means that applying the same functor twice to the same argument always yields fresh types.
In OCaml, functors are applicative, which means that applying the same functor twice to the exact same argument (plus additional syntactic restrictions) reproduces equivalent types. This semantics is more flexible, but can also break abstraction (see e.g. the examples we give in this paper, Section 8).
Edit: OCaml 4 added the ability to optionally make functors generative.
OCaml has a purely syntactic notion of signatures, which means that certain type equivalences cannot be expressed by the type system, and are silently dropped.
Edit: Consider this example:
module F (X : sig type t end) = struct type u = X.t -> unit type v = X.t end
module M = F (struct type t = int end : sig type t end)
The type of M is simply sig type u type v end and has thus lost any information about the relation between its types u and v, because that cannot generally be expressed in the surface syntax.
Another notable difference is that OCaml's module type system is undecidable (i.e, type checking may not terminate), due to its permission of abstract signatures, which SML does not allow.
As for semantics, a much better and elaborate answer is given by Andreas Rossberg above. However, concerning syntax this site might be what you are looking for.
There is also the abstype facility in SML which is like the datatype facility, except that it hides the structure of the datatype. OCaml relies on module abstraction to do all the hiding that is necessary. Notice that this site does not mention this facility in SML.