I realize some of these aren't possible, but theres no harm in voicing some thoughts:
Statically-checked structural typing. For example, the function
let f x = x#someMethod()
Should accept any x
so long as it has a method val someMethod : unit -> 'a
.
Just one way to do it. I think in the beginning, OCaml compatibility was very important, leading to the development of a #light and non-light syntax, two mutually incompatible syntaxes for defining classes, and a bagillion different ways to define objects with generic parameters:
type 'a tree =
| Node of 'a * 'a tree * 'a tree
| Empty
type tree2<'a> =
| Node of 'a * tree2<'a> * tree2<'a>
| Empty
type tree3<'a when 'a :> System.IComparable<'a> > =
| Node of 'a * tree3<'a> * tree3<'a>
| Empty
type 'a tree4 when 'a :> System.IComparable<'a> =
| Node of 'a * tree4<'a> * tree4<'a>
| Empty
type ('a, 'b) tree5 =
| Node of 'a * 'b * ('a, 'b) tree5
| Empty
type tree6<'a, 'b> =
| Node of 'a * 'b * tree6<'a, 'b>
| Empty
type tree7<'a, 'b> when 'a :> System.IComparable<'a> and 'b :> System.IComparable<'b> =
| Node
Now that #light is enabled by default and the F# library no longer cross-compiles with OCaml, we should consider OCaml compatibility no longer relevant. The language needs to be simplified.
Type signature should match type annotations: When I write a method like this:
let f (x : 'a :> #System.IComparable<'a>) = x
F# reports the type signature as val f : 'a -> 'a (requires 'a :> System.IComparable<'a>)
. I'd prefer to see the type signature reported exactly as written: val f : ('a :> #System.IComparable<'a>) -> 'a
.
Intellisense should report variable names: Its hard to know what I'm calling when I can't see variable names. Case in point, F# lists the constructors for the StringBuilder class as follows:
val new : unit -> System.Text.StringBuilder
val new : int -> System.Text.StringBuilder
val new : string -> System.Text.StringBuilder
val new : string * int -> System.Text.StringBuilder
val new : string * int * int * int -> System.Text.StringBuilder
val new : int * int -> System.Text.StringBuilder
I've created a bagillion StringBuilders and know how to use most of these, but I keep having to go back to MSDN to figure out what exactly I'm passing in. I've figured out how to get constructor parameters by writing System.Text.StringBuilder;;
into fsi, which gives me this output:
stdin(1,1): error FS0191: Invalid use of a type name and/or object constructor. If necessary use 'new' and apply the constructor to its arguments, e.g. 'new Type(args)'. Overloads are:
System.Text.StringBuilder() : unit
System.Text.StringBuilder(capacity: int) : unit
System.Text.StringBuilder(value: string) : unit
System.Text.StringBuilder(value: string, capacity: int) : unit
System.Text.StringBuilder(capacity: int, maxCapacity: int) : unit
System.Text.StringBuilder(value: string, startIndex: int, length: int, capacity: int) : unit
Barring changes to Intellisense, I'd just like some way to quickly expore type signatures. C# has an interesting feature where I can press F12 on any class, like the StringBuilder class, and it'll pull up a window with the class's complete public signature similar to what fsi shows above. The object browser works for now, but its too slow and doesn't always show me all the information I'm interested in seeing (i.e. it doesn't show me an object's base class).
Functional alternatives to existing libraries: this probably isn't the responsibility of the F# team, maybe it should be an open source project, but the .NET libraries don't make functional programming very easy. Everything in System.Data, the Microsoft Enterprise Library, and some third-party libraries like NHibernate rely heavily on mutable state.