let stringResult = aString |> Seq.map (fun c -> Char.ToUpper(c)) // returns seq<char>, not String, not expected
let listResult = aString |> Seq.map(fun c -> int c) // returns seq<int> as expected
And in both cases you specifically had to point out the function that F# uses and you lost type information in the first case.
I don't agree with your comments on erasure & type classes. The reified types wouldn't help Scala one bit to achieve their collection library. (I'm not saying that reified types aren't usefull, just that they don't help here)
And I see now that by functional datastructures, they mean efficient persistent datastructures. So, does F# have datastructures (Lists, Sets, Maps) that are immutable and have a very efficient (close to O(1)) update and delete operations?
@Petr: You use Set.filter, that's cheating, can you write
let filtered = set |> filter (fun elm -> elm = 2)?
(you can in Haskell, but I don't think F# has type classes or type constructors)
In scala filter is implemented once, for all collections (of course some collections override & specialize for performance), it still supports the uniform return type principle and you don't need to tell it specifically what function it has to call.
In F# you have to reïmplement filter for all collections and then you still can't handle my last example with strings.
@Petr: Haskell, Ocaml, ml etc have functional datastructures as well but they don't apply the uniform return type principle in their collections.
val aSet = Set(1, 2, 3)
val result = aSet.filter(x => somePredicate(x))
In Scala the type of 'result' will be a Set[Int], in F# & C# it will be an IEnumerable. Scala is one of the few languages that has a type system that is powerfull enaugh to allow this trickery.
Of course Scala can have behave similarly as F# or C# if you want it to (aSet.iterator.filter... )
A more powerfull example:
val aString = "string"
val stringResult = aString.map(c => c.toUpper) // result is a String: "STRING"
val listResult = aString.map(c => c.toInt) // result is a Vector[Int]: Vector(115, 116, 114, 105, 110, 103)