On F#

By chance I have got interested in F#, although I have been and will be a happy O'Caml programmer. In fact I have never imagined that I would seriously try to use programming languages which do not support polymorphic variants. They are too useful to miss!
Yet of cource it is useful to learn other languages and I will keep possibly biased notes on F# as long as I have good appetites.

Please correct me when you find my misunderstandings and lack of knowledge in this note. My e-mail address should be found somewhere.

Disclaimer: I have noticed that my view is often in favor of OCaml. So please bear it in mind if you are to read this notes.

06/11/2007

Now F# is running with mono on my vaio laptop, where FreeBSD 6.2 is installed. I had to upgrade xorg to 7.2 to install libgdiplus, which F# seems to require. Everything was taken care of by the ports system. Caution: install-mono.sh* in the distribution is in the DOS format (CR/LF); you may have to convert it to Unix format (LF) (e.g. cat install-mono.sh | tr -d '\r' > install-mono_unix.sh).

One reason that F# interests me is its nominal object system. Although I am fond of OCaml's structural object system, I have been curious about nominal object systems, too. Unfortunately I have never exploited the full power of the object systems, like inheritance or overriding; now I will enjoy it through F#!

Having a nominal object system, type inference shall need some amount of type annotation. Indeed,

> let f x = x.callMe ();;
does not type check; but I need to assist the inference engine as in
> type c = class  
    new () = {} 
    self.callMe () = 3 
  end;;
> let f (x:c) = x.callMe ();;
This is a difference from OCaml, where the object system is structural, and where the annotation on f's parameter is unneccessary but the type inference can take care of it. By the way, how do they infer types? (ref.)

Like OCaml, subtyping is explicit (if I understand correctly). Yet, like OCaml, polymorphism is available. So

> type A = class
    new () = {}
    member self.f x = x
  end;;
> type B = class
    inherit A
    new () = {}
  end;;
> let a = new A ();;
> let b = new B ();;
I need explicit coercion if I fixed type:
> let callA (x:A) = x;;
> let _ = callA a;;
> let _ = callA (b :> A);;
Yet I can define polymorphic callA, which does not require coercion:
> let callpolyA (x:#A) = x;;
> let _ = callpolyA a;;
> let _ = callpolyA b;;
Anyway I like explicit subtyping as a programming practice.

09/11/2007

In F# a type constructor can escape from its scope; this is a little difference from OCaml. That is, the following code only causes a warning, but not a type error.
> let f x y = (x, y);;
> let g = f 3;;
> type t = A;;
> let x = g A;;
Since F# supports neither functors nor local modules, strict conformity to the scope is not crucial perhaps.

12/11/2007

I have an idea. Let's try to translate OCaml manual on objects into the F# vocabulary. In this way, I will learn both OCaml's structural object system and F#'s nominal object system at once :-)

Chapter 3.1 Classes and objects

> type point = class
  val mutable x : int
  new () = {x = 0}     
  member self.get_x = self.x
  member self.move d = self.x <- self.x + d 
end;;
type point = class
               val mutable x: int
             end
             with
               new : unit -> point
               member get_x : int
               member move : d:int -> unit
             end

Note the separation between field declarations and their initialization; I like this programming style.
> let p = new point ();;
val p : point
>  p.get_x;;
val it : int = 0 
> p.move 3;;
val it : unit = null
> p.get_x;;
val it : int = 3
> p.x;;
val it : int = 3
A big difference between OCaml and F#: in OCaml an instance variable is not visible outside the object, whereas in F# a field is visible outside the object.
> let x0 = ref 0;;
val x0 : int ref

> type point2 = class
  val mutable x : int
  new () = incr x0; {x = !x0}
  member self.get_x = self.x
  member self.move d = self.x <- self.x + d
end;;
Above I see another interesting design choice. Side effecting expressions are syntactically separated from initialization expressions. (ref) For now I do not know the impact of this design choice; but it looks interesting.
> (new point2 ()).get_x
val it : int = 1 

> (new point2 ()).get_x
val it : int = 2
Now I see a divergence from OCaml; there is no faithful correspondence to the following class definition from OCaml manual:
#class point3 = fun x_init ->
   object 
     val mutable x = x_init
     method get_x = x
     method move d = x <- x + d
   end;;
In a structural object system, class definitions are, broadly speaking, function definitions. (OCaml generates from class definitions type abbreviations. Although this is very useful for the practical use in my opinion, abbreviation generation is dispensable from a theoretical point of view.) In a nominal object system however, class definitions define both values and types simultaneously, which seems to hinder the translation of the above class definition into F#. (e.g., In a nominal system distinct class definitions necessarily generate distinct types, which is not the case in a structural system.)

Here is a slightly different version:

#class point3 x_init =
   object 
     val mutable x = x_init
     method get_x = x
     method move d = x <- x + d
   end;;
A natural translation into F# may be
> type point3 = class
  val mutable x:int
  new (x_init) = {x = x_init}     
  member self.get_x = self.x
  member self.move d = self.x <- self.x + d
end;;
> fun x_init -> new point3 (x_init);;
val it : int -> point3 = <...>
> >let p = new point3 7;;
val p : point3
Be careful fun x_init -> new point3 x_init is syntax error; parentheses are mandatory.

13/11/2007

A difference between structural and nominal objects also appears when translating the following OCaml class:

#class point4 x_init =
   object 
     val mutable x = x_init
     method get_x = x
     method get_offset = x - x_init
     method move d = x <- x + d 
   end;;
The following F# class may be a natural translation.
> type point4 = class
  val  x_init: int
  val mutable x:int
  new (init) = {x = init; x_init = init}
  member self.get_x = self.x
  member self.get_offset = self.x - self.x_init
  member self.move d = self.x <- self.x + d
end;;
You see the difference. The parameter x_init is visible in the whole body of the class definition point4 in OCaml, which is not the case in F#, thus point4 in F# has an extra field. (Both may be boiled down to the same closure. Note that the x_init field of F# point4 is immutable.)

16/11/2007

Here is a derivative of the above observation. (No corresponding code in OCaml manual)
#class point5 x_base x_init=
   object 
     val mutable x = x_init
     method get_x = x
     method get_offset = x - x_base
     method move d = x <- x + d 
   end;;
#let point_0 = new point5 0 
> type point5 = class
   val  x_base: int
   val mutable x:int
   new (base, init) = {x_base = base; x = init}
   member self.get_x = self.x
   member self.get_offset = self.x - self.x_base
   member self.move d = self.x <- self.x + d
  end;;
>  let point_0 = fun init -> new point5 (0, init)
Are OCaml point_0 and F# point_0 ultimately same?

Return to the OCaml manual where adjusted_point is defined.
> type adjusted_point = class
   val mutable x: int
   val origin: int
   new (init) = let x_init = (init / 10) * 10 in { x = x_init; origin = x_init}
   member self.get_x = self.x
   member self.get_offset = self.x - self.origin
   member self.move d = self.x <- self.x + d
  end;;
I re-remembered a difference between structural and nominal objects. In OCaml all classes of point, point2 and point3 are equivalent types, whereas in F# they are distinct. So to make my encoding semantically closer to the original (i.e., OCaml manual), I should have first defined an interface and let the classes implement the interface so that these classes can be coerced into the same interface.

So there is no exact correspondence in F# to the following OCaml class definition.

#class adjusted_point x_init = point4 ((x_init / 10) * 10);;
A close definition may be this:
> type adjusted_point = class
   inherit point4
   new (init) = let x_init = ((init / 10) * 10) in = { inherit point (x_init)}
  end;;
Again two classes point4 and adjusted_point are equivalent in OCaml, whereas they are distinct in F#. (adjusted_point is coercible to point4, but not vice versa.)

The following two functions may correspond exactly.

#let new_adjusted_point x_init = new point4 ((x_init / 10) * 10);;
>  let new_adjusted_point x_init = new point4 ((x_init / 10) * 10);;

23/11/2007

Chapter 3.2 Immediate objects

Immediate objects of OCaml and F# do not exactly correspond in a sense that in F# the type of an immediate object must have been generated before the object creation.

Below are the two things I have learned. (ref.)

From the OCaml manual:
> type mm = class
    new () = {}
    abstract min : int
    abstract max : int
  end;;
> let minmax x y = 
   if x < y then {new mm () with member self.min = x member self.max = y end}
   else {new mm () with member self.min = y member self.max = x end};;
val minimax : int -> int -> mm
I could have relied on implicit constructors:
> type mm2 (min: int, max: int)= class
    member self.min = min
    member self.max = max
  end;;
> let minmax2 x y = if x < y then new mm2 (x, y) else new mm2 (y, x);;
val minmax2 : int -> int -> mm2
However, as far as I know, implicit constructors are under design or under implementation; at least I am not able to find documentation describing its general treatment. Usually I do not use constructs that I cannot understand, hence I will not use implicit constructors for the moment.

Chapter 3.3 Reference to self

> type printable_point = class 
    val mutable x: int
    new (init) = { x = init }
    member self.get_x = self.x
    member self.move d = self.x <- self.x + d
    member self.print = print_int self.get_x; print_newline ()
  end;;
> let p = new printable_point 7;;
> p.print;;
7
val it : unit = null
If I understand correctly, F# does not have explicit self variables. Indeed, I was rather surprised by this result of the type inference:
> type c = class member self.me = self end;;
type c = class
         end
         with
           member me : c
         end

3/12/2007

Chapter 3.4 Initializers

> type printable_point2 = class
     val mutable x:int
     new (init) as this = 
       let origin = (init / 10) * 10 in { x = origin }
       then print_string "new point at "; this.print; print_newline()
     member self.get_x = self.x
     member self.move d = self.x <- self.x + d
     member self.print = print_int self.get_x
  end;;
> let p = new printable_point2 17;;
val p : printable_point2
new point at 10
Object initialization appears different between OCaml and F#. So let's examine it in more detail.
> let print i = print_int i; print_newline ();;
> type c1 = class
   val x: int
   new () as this = { x = 0 } then print this.x
  end
> new c1 ();;
0
It is safe to dereference this within the trailing expression.
> type c2 = class
   val x1: int
   val x2: int
   new () as this = { x1 = 0; x2 = this.x1 }
  end;;
warning: .... < the possibility of a null pointer exception > ...
> new c2 ();;
System.NullReferenceException
> type c3 = class
   val x: c3
   new () as this = { x = this }
  end;;
warning: .... < the possibility of a null pointer exception > ...
> new c3 ();;
System.NullReferenceException
> let discard x = 0;;
> type c4 = class
   val x: int
   new () as this = { x = discard this }
  end;;
warning: .... < the possibility of a null pointer exception > ...
> new c4 ();;
System.NullReferenceException
Ok. this is evaluated (dereferenced?) even if I do not access its fields. But a reference to this should be safe if it occurs under abstraction:
> type c5 = class
   val x: unit -> c5
   new () as this = { x = fun () -> this }
end;;
error: binding null type in envBindTypeRef: .ctor@3
What does this error mean? Anyway c5 type checks with fsc.

7/12/2007

Handling of object initialization is very different between OCaml and F#. Probably I will recognize more differences as I learn F# more. Below are the two things that I hit first.

1) In F# I have access to "base", i.e., the inherited object, during object construction.

> type c6 = class
    val i1: int
    new (init) = { i1 = init }
  end;
> type c7 = class
    inherit c6 as base
    val i2: int
    new (init) = { inherit c6(init); i2 = base.i1 * 2 }
  end;;
> let x = new c7 3;;
> x.i1;;
val it : int = 3
>  x.i2;;
val it : int = 6
There is no equivalent in OCaml side. (Of course, you have encodings for a similar effect.)

2) Side effecting expressions before/after object construction interact with inheritance in different ways.

> type c8 = class
    val i1: int
    new (init) = let _ = print_string "A" in 
                 { i1 = (print_string "B"; init) } 
                 then print_string "C"
  end;;
> type c9 = class
    inherit c8
    val i2: int
    new (init) = let _ = print_string "D" in 
                 { inherit c8 (init); i2 = (print_string "E"; init) } 
                 then print_string "F"
  end;;
DABCEF
#class c8 init = 
   let _ = print_string "A" in 
   object 
     val i1 = (print_string "B"; init)
     initializer print_string "C"
    end;;
#class c9 init = 
   let _ = print_string "D" in 
   object 
     inherit c8 init
     val i2 = (print_string "E"; init)
     initializer print_string "F"
   end;;
DABECF
As a result, F#'s design lets me observe a null-pointer exception:
> type c10 = class
   new () as this = {} then this.f ()
   abstract f: unit -> unit
  end;;
> type t = A of int;;
> type c11 = class
   inherit c10
   val data: t
   new () = { data = A 0 }
   override self.f () = match self.data with A i -> print_int i
  end;;
System.NullReferenceException;;
I am a little unhappy that the compiler does not even warn me the possibility. It's not fair of me to complain about it, considering F#'s interoperability with .NET languages :-)

Chapter 3.5 Virtual methods

> type abstract_point = class
    val mutable x: int
    val x_init: int
    new (init) = { x = init; x_init = init }
    abstract get_x : int
    member self.get_offset = self.get_x - self.x_init
    abstract move: int -> unit
  end;;
type abstract_point = class
                        abstract member get_x : int
                        abstract member move : int -> unit
                        val mutable x: int
                        val x_init: int
                      end
                      with
                        new : init:int -> abstract_point
                        member get_offset : int
                      end
> type point7 = class
    inherit abstract_point 
    new (init) = { inherit abstract_point (init) }
    override self.get_x = self.x
    override self.move d = self.x <- self.x + d
  end;;
type point7 = class
                inherit abstract_point
              end
              with
                new : init:int -> point7
              end
One thing I feel unconformable about virtual classes of F# is that there is no explicit keyword, like the OCaml's virtual keyword, specifying that a class is virtual, hence is not instantiatable. Although the compiler gives me a warning, the type of a class does not necessarily indicate whether the class is virtual or not. For instance:
> type point8 = class
    inherit abstract_point 
    new (init) = { inherit abstract_point (init) }
    override self.get_x = self.x
  end;;
type point8 = class
                inherit abstract_point
              end
              with
                new : init:int -> point8
              end
Of course, I cannot instantiate point8; such attempt is statically rejected. i.e., new point8 0 is a compile-time error.

17/12/2007

As far as I understand, there is no correspondence in F# to virtual instance variables of OCaml.

3.6 Private methods

According to the latest release note, F# is to support access controls. I will come back to these sections about restricting visibility, when the extension becomes solid and more information becomes available.

3.7 Class interfaces

> type restricted_point_type = class
    abstract get_x: int
    abstract bump: unit
  end;;
> fun (x: restricted_point_type) -> x;;
val it : restricted_point_type -> restricted_point_type = <...>
I do not think there is a F# equivalent of the following OCaml class definition.
#class restricted_point' x = (restricted_point x : restricted_point_type);;
class restricted_point' : int -> restricted_point_type
Indeed this mechanism looks particular to structural object systems, where class definitions do not generate nominal types. Note that this is not same as constraining (object) constructors, since the class restricted_point' is still inheritable.
#class restricted_point2' = object
  inherit restricted_point' 0
  method move = "I will not move"
end;;
Is it meaningful to make a comparison between OCaml and F# on this behavior, considering that instance variables and concrete private methods can be hidden here? Remember that both of instance variables and concrete private methods are invisible to object clients, but are only visible to class clients.

3.8 Inheritance

> type colored_point  = class
    inherit point4
    val c : string
    new (x,c) = { inherit point4 (x); c = c }
    member self.color = self.c
  end;;
type colored_point = class
                       inherit point4
                       val c: string
                     end
                     with
                       new : x:int * c:string -> colored_point
                       member color : string
                     end
> let p' = new colored_point (5, "red");;
val p' : colored_point
>  p'.get_x, p'.color;;
val it : int * string = (5, "red")

3.9 Multiple inheritance

In F#, an overridable method should be marked in advance when declaring the method for the first time. I like this style. So let me redefine printable_point.
> type printable_point3 = class
     val mutable x:int
     new (init) as this = 
       let origin = (init / 10) * 10 in { x = origin }
       then print_string "new point at "; this.print; print_newline()
     member self.get_x = self.x
     member self.move d = self.x <- self.x + d
     abstract print : unit
     default self.print = print_int self.get_x
  end;;
> type printable_colored_point = class
     inherit printable_point3 as super
     val c:string
     new (y, c) = { inherit printable_point3 (y); c = c }
     member self.color = self.c
     override self.print =
       print_string "(";
       super.print;
       print_string ", ";
       print_string (self.color);
       print_string ")"
  end;;
> let p' = new printable_colored_point (17, "red");;
new point at (10, )
Why...? Yes, I remembered the order in which trailing expressions are evaluated.
> p'.print;;
(10, red)

20/12/2007

3.10 Parameterized classes

> type ref = class
    val mutable x:int 
    new (x_init) = { x = x_init }
    member self.get = self.x
    member self.set y = self.x <- y
  end;;
> type 'a ref2 = class
    val mutable x : 'a
    new (x_init) = { x = x_init}
    member self.get = self.x
    member self.set y = self.x <- y
  end;;
> let r = new (_ ref2) 1 in r.set 2; r.get;;
val it : int = 2
Below is a little experiment.
> type 'a ref_succ = class
    val mutable x: 'a
    new (x_init) = { x = x_init + 1 }
    member self.get = self.x
    member self.set y = self.x <- y
  end;;
stdin(3,2): error: This code is not sufficiently generic. 
The type variable  ^a when  ^c : (static member ( + ) :  ^c * int ->  ^a) 
could not be generalized because it would escape its scope.
I do not well-understand what this error message means. Yet let me try with another example.
> type succ = class
    val mutable x:int
    new (x) = { x = x }
    member self.get = self.x
    abstract set: int -> unit 
    default self.set y = self.x <- y
  end;;
> type 'a ref_succ when 'a :> succ = class
    val x: 'a
    new (x) = { x = x }
    member self.get = self.x.get
    member self.set y = self.x.set y
  end;;
> type succ_double = class
    inherit succ
    new (x) = { inherit succ (x) }
    override self.set y = self.x <- y*2
  end;;
> let x = new succ_double 3;;
> let y = new (_ ref_succ) (x);;
My conclusion is that, probably, F# does not infer constraint unlike OCaml.

28/12/2007

Some experiments, not along the OCaml manual.
> let _ = (y :> succ ref_succ);;
error
As written in the manual (see the 3rd entry of "The Coercion Relation" paragraph), F# generic types do not support co-variance or contra-variance.

Below type checks.

> type 'a ref_succ_double when 'a :> succ_double = class
   inherit 'a ref_succ
   new (x) = { inherit ('a ref_succ) (x) }
  end;;
> let z = new (_ ref_succ_double) (x);;
> let z' = (z :> succ_double ref_succ);;
val z' : succ_double ref_succ
The type checker rejects untyped inheritance such as:
> type 'a ref_succ_bad = class
   inherit 'a ref_succ
   new (x) = { inherit ('a ref_succ) (x) }
  end;;
error

Now I return to the OCaml manual.

#class ['a] circle (c : 'a) = object 
  constraint 'a = #point
  val mutable center = c
  method center = center
  method set_center c = center <- c
  method move = center#move
  end;;
> type 'a circle when 'a :> point4 = class
    val mutable c: 'a
    new (c) = { c = c }
    member self.center = self.c
    member self.set_center c = self.c <- c
    member self.move = self.c.move
  end;;
type 'a circle when 'a :> point4 = class
                                     val mutable c: 'a
                                   end
                                   with
                                     new : c:'a -> 'a circle
                                     member center : 'a
                                     member move : (int -> unit)
                                     member set_center : c:'a -> unit
                                   end
OCaml uses row polymorphism, whereas F# uses subtyping polymorphism. (I hope my understanding is correct.) Besides compare the above F# circle with the following circle2:
> type 'a circle2 when 'a :> point = class
    val mutable c: 'a
    new (c) = { c = c }
    member self.center = self.c
    member self.set_center c = self.c <- c
    member self.move x = self.c.move x
  end;;
type 'a circle2 when 'a :> point4 = class
                                      val mutable c: 'a
                                    end
                                    with
                                      new : c:'a -> 'a circle2
                                      member center : 'a
                                      member move : x:int -> unit
                                      member set_center : c:'a -> unit
                                    end;;
circle2 looks closer to the OCaml circle in respect of types.
> type 'a colored_circle when 'a :> colored_point = class
    inherit 'a circle2
    new (c) = { inherit (_ circle2) (c) }
    member self.color = self.c.color
  end;;
type 'a colored_circle when 'a :> colored_point =
  class
    inherit 'a circle2
  end
  with
    new : c:'a -> 'a colored_circle
    member color : string
  end

3.11 Polymorphic methods

I do not know whether F# supports polymorphic methods.

11/1/2008

3.12 Using coercions

> let colored_point_to_point cp = (cp : colored_point :> point4);;
error: syntax error

> let colored_point_to_point (cp : colored_point) = (cp :> point4);;
val colored_point_to_point : colored_point -> point4
Indeed there would be no reason that F# needs to support OCaml style double coercion, since the necessity comes from the interaction between subtyping and the full type inference.
> let p = new point4 3 and q = new colored_point (4, "blue");;
val q : colored_point
val p : point4
> let l = [p; (colored_point_to_point q)];;
val l : point4 list
> (p  :> colored_point);;
error: Type constraint mismatch.
Unfortunately and fortunately, F# supports dynamic type tests.
> let q' = colored_point_to_point q;;
(q'  :> colored_point);;
error: Type constraint mismatch.
(q'  :?> colored_point);;
val it : colored_point = ...
> let to_point (cp: #point4) = (cp :> point4);;
val to_point : #point4 -> point4
> let colored_point_to_point2 (cp : #colored_point) = (cp :> point4);;
val colored_point_to_point2 : #colored_point -> point4

3.13 Functional objects

3.14 Cloning objects

Does F# support the functionality of cloning objects? But in the absence of self types, it will not bear a close connection to the OCaml cloning functionality.

23/1/2008

3.15 Recursive classes

> type window = class
  val mutable _top_widget : widget option
  new () = { _top_widget = None }
  member self.top_widget = self._top_widget
end
and widget = class
  val _window: window
  new (w) = { _window = w}
  member self.window = self._window     
end;;

3.16 Binary methods

I do not think F# handles binary methods.

3.17 Friends

I will investigate implicit object creation and access controls to members of objects when these features become solid and more documentation becomes available.

Jottings on error massages.
?
An observation on F# objects