API's that Suck

June 4, 2009

F#: Static Typing Done Horribly Wrong

Filed under: Uncategorized — Grauenwolf @ 7:01 pm

The Some operator in F# almost shouldn’t exist. There is one and only one instance where it makes sense.

let mutable a = Some(5)

That’s it. At no other time you should ever have to use it. Consider this silly little function.

let Foo (arg1 : int option, arg2 : int option) = 
    match arg1, arg2 with
    | None, None -> 0
    | arg1, None -> arg1.Value
    | None, arg2 -> arg2.Value
    | _, _ -> arg1.Value + arg2.Value

Normally I pass values of option<int> to it, but once in awhile I would like to pass a normal int.

let b = Foo(a, 5) // Error: This expression has type  int but is here used with type  int option

So? You don’t have to understand that the set of all option<int> values contains all int values. Or in other words, it is always safe to convert a int into an option<int>. I’ll even go one step further. It is always safe to convert any T into any option<T>.

SO WHY ARE YOU WASTING MY TIME?

Ok, lets try something a little bit easier. Every language high on the chain than assembly knows about implicit numeric conversions, right? Well lets try that with F#.

let c = 10
let d = (decimal)2.5
let e = c + d //Type constraint mismatch. The type int is not compatible with type decimal

What do you mean “the type int is not compatible with the type decimal”? Every possible int can be exactly represented as a decimal, so what the heck are you complaining about?

Maybe I’m using it wrong. Maybe I should try F#’s famous automatic generalization of functions.

let SimplyAdd x y = x + y //Type constraint mismatch. The type int is not compatible with 
type decimal The type 'int' is not compatible with the type 'decimal'
let f = SimplyAdd c d //Type constraint mismatch. The type int is not compatible with type
decimal The type 'int' is not compatible with the type 'decimal'

Cool. Now I got errors on tow separate lines, and they each tell me the same thing twice.  Where else can you get four error messages for the price of one type conversion?

If the F# designers were to put in just a little bit of compiler magic so that the language would do the semantically right thing, F# would be a really pleasant language to work with.  But like the way they introduced option-style nulls without removing CLR nulls, making something technically consistent at the expense of both inconsistent syntax and inconsistent semantics is just wrong.

About these ads

10 Comments »

  1. First, before sounding off, it’s best to understand where F# has its lineage. F# comes from influences from the OCaml language, Haskell and a little bit of C# to boot.

    Why Option/Maybe types make sense is to ensure what is explicitly a failure and what isn’t. Is -1 a failure, how about null? Here are some good posts on the matter.
    Why I Love F# Option Types: http://diditwith.net/2008/02/25/WhyILoveFOptionTypes.aspx
    Haskell Maybe: http://en.wikibooks.org/wiki/Haskell/Hierarchical_libraries/Maybe

    You stated incorrectly that most languages do automatic number conversion. This of course isn’t true. Since F# has its lineage in both Haskell and OCaml, it very much follows the number conversion logic of those languages. The reason is quite simple for this, because adding unlike numbers can produce unintended consequences. Did you want any rounding to occur or not? I’d rather be explicit, especially around the ideas of mathematical purity that is at the heart of Functional Programming. Read here for more details:
    OCaml: http://www.ocaml-tutorial.org/the_basics
    “OCaml never does implicit casts like this. In OCaml, 1 + 2.5 is a type error. The + operator in OCaml requires two ints as arguments”
    Haskell: http://www.haskell.org/haskellwiki/Converting_numbers

    Before going off on rants such as these, please do spend some time in the language to understand its roots. The F# books available right now do have some great material on the motivations of the Option type such as Don Syme’s Expert F#.

    Matt

    Comment by Matthew Podwysocki — June 4, 2009 @ 10:46 pm

    • I’m not really interested in F# as a homage to OCaml and ML. I’m interested in F# as a tool for writing applications using a functional style on the .NET runtime in the most efficient manner possible.

      Comment by grauenwolf — June 5, 2009 @ 8:18 pm

    • This comment doesn’t make any sense at all to me.

      > The reason is quite simple for this, because adding unlike numbers can produce unintended consequences. Did you want any rounding to occur or not?

      When you convert from an int to a decimal, rounding never occurs. It doesn’t matter what integer you choose, it will always be represented exactly in a decimal.

      Comment by grauenwolf — June 5, 2009 @ 8:25 pm

      • Only if you wanted that to be a decimal in the first place and that was my point. I for one like the explicit nature of those operators and to me it’s not a hardship.

        I really think you ought to be interested in the homage because that’s where you really start to understand functional programming instead of this rant which didn’t seem to make much sense to me. Remember that F# was written in the beginning to have OCaml compatibility and that’s where these constructs came from.

        As for the automatic conversion to and from option, well that is part of the OOP syntax for F# but I’m not sure it’s going to make it to VS2010. I hope it does.

        Comment by Matthew Podwysocki — June 5, 2009 @ 8:45 pm

  2. Might want to have a read; Or if you don’t have the time, Chance Coble has done the work for you http://leibnizdream.wordpress.com/2007/12/10/f-some-common-mistakes/

    Comment by thinkhard — June 5, 2009 @ 6:30 pm

  3. I totally agree with this rant. I don’t program to be technically pure, I solve problems. And I don’t need a language that thinks it knows what’s best and gets in my way to prove. Ada was already invented for that.

    Comment by NetMage — July 21, 2009 @ 6:21 pm

  4. The benefits of static typing are diminished with implicit coercions like you’re suggesting.

    Comment by Sandro Magi — August 17, 2009 @ 3:43 pm

    • What benefit? Typing practice?

      Static typing is there to catch errors. Converting from an integer to a decimal is never an error, so there is nothing to catch.

      Comment by grauenwolf — August 19, 2009 @ 4:11 pm

      • Static typing is here to catch errors? Think again when it comes to OCaml/F#.

        Static typing is here to emphasise the semantics of your program.

        Mistaking an integer for a decimal is a semantic misconception.

        You want operator overloading, so that you can “convert from an integer to a decimal”? Sure, there won’t be errors… but overloading will get in your way when debugging something else somewhere else in your code.

        I also thought at one point that there should be some sort of automatic conversion for some issues. Seems simple at first glance. At second glance, it gets horrible. Say you have “a + (b + c)”. Do you want to handle all cases for conversion possibilities when you have a type inference going wrong?

        I do not: I’d rather use the BENEFITS of static typing typing… i.e. finding SEMANTIC errors quickly due to TYPE INFERENCE and have a QUICK coding/compiling cycle.

        Just try to level up your notion of error from “segfault” to “semantics”, and you’ll see that type inference is not simply a better way to statically type memory usage as in C… it’s semantics that you’re typing, not merely the ocurrence of NULL pointers.

        And I love None / Some… and nice code is code that doesn’t use None / Some much because its semantics are well thought out, in such a way that you do not need such option types.

        In OCaml/F# you think more than you code, in order to code much faster in the medium to long run.

        Comment by yziquel — February 26, 2010 @ 3:50 pm

      • Lack of an error does not imply that the type coercions respect equational reasoning. Static typing is intended to allow the developer to express the semantics of the application domain in a way the compiler can verify for consistency in a well-founded equational theory.

        Unprincipled implicit coercions defeat this purpose since what the developer types and what the compiler does may be at odds, without the user ever knowing. Type classes are an exception here since they respect proper equational reasoning.

        Comment by Sandro Magi — May 1, 2010 @ 5:41 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The WordPress Classic Theme. Create a free website or blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: