Friday, January 18, 2008
Another feature of the F# language that I crave desperately when writing C# or VB code is F#'s built-in support for tuples. What's a tuple? Simply put, a tuple is an ordered group of values. In one sense, a tuple is very similar to the anonymous types of C# 3.0. The chief difference is that the values in an F# tuple are not named like the properties of a C# anonymous type.
NeRd Note
Most pressing on your mind is likely the question of how one pronounces the word, "tuple." Well, my British friends emphatically point out that it's "too-pull," while my red-blooded, English-language-abusing American friends1 like to say "tuh-pull."2 However, when my British friends speak, they always sound intelligent. I think it has something to do with the accent. So, I'm going with "too-pull." I like to sound smart—especially when it's easy.

In F#, a tuple3 is concisely declared as a let statement with a single name and multiple values separated by commas.

> let pair = 37, 5;;

val pair = int * int

> pair;;

val it : int * int = (37, 5)

Notice that F# infers the type of pair to be int * int. The asterisk (*) doesn't actually mean multiplication in this case. Instead, it indicates that the two types on either side are bound together as one type.

Tuples can contain any number of values, and the values don't have to be of the same type.

> let triple = 0, "F# Rules!", 12.8;;

val triple : int * string * float

Tuples can be compared for equality.

> pair = (29, 13);;

val it : bool = false

> pair = (37, 5);;

val it : bool = true

> pair = (19, 23);;

val it : bool = false

And other comparisons are also legal.

> (1, 1) < (1, 2);;

val it : bool = true

> (2, 1) > (1, 2);;

val it : bool = true

However, tuples with different types cannot be compared. Trying to compare pair, which is of type int * int, with a tuple of type int * string results in an error:

> pair = (0, "F# Rules!");;

  pair = (0, "F# Rules!");;
  -----------^^^^^^^^^^^^

stdin(12,11): error: FS0001: This expression has type
        string
but is here used with type
        int
stopped due to error

In addition, tuples of different lengths cannot be compared.

> triple = (0, "F# Rules!");;

  triple = (0, "F# Rules!");;
  ----------^^^^^^^^^^^^^^^

stdin(13,10): error: FS0001: Type mismatch. Expecting a
        int * string * float
but given a
        'a * 'b.
The tuples have different lengths
stopped due to error

Interestingly, in the above code, the F# compiler doesn't bother inferring the types in the tuple, (0, "F# Rules!"). It is left generic: 'a * 'b. The F# compiler sees that the tuples have a different number of values and stops.

Next time we'll look at some cool ways to use tuples in F# programming.

1Please don't hurt me Keith!
2Usually while sucking down a can of Schlitz.
3too-pull

posted on Friday, January 18, 2008 1:14:39 PM (Eastern Standard Time, UTC-05:00)  #    Comments [5]

kick it on DotNetKicks.com
Friday, January 18, 2008 1:59:26 PM (Eastern Standard Time, UTC-05:00)
OK, you win. I think F# is about the coolest language I've seen in long time. It has bothered me to no end while using C# when I don't just have a tuple. Whenever I prototype anything I like using Python (another great language IMHO)

And for the record, I'm from the United States and I pronounce "tuple" as "too-pull". Having only 1 "p" and with the "e" on the end it is obvious how the "u" should be pronounced in that word. It always bugs me when people say "tuh-pull". If it were meant to be pronounced that way it would be spelled "tupple".

I've seen plenty of references citing it one way or the other, but I'm just going to use some (mostly) standard English language rules.
Friday, January 18, 2008 2:03:39 PM (Eastern Standard Time, UTC-05:00)
> OK, you win. I think F# is about the coolest language I've seen in long time.

Just wait -- it gets better. We're only touching basic stuff so far. :-)
Saturday, January 19, 2008 3:26:40 AM (Eastern Standard Time, UTC-05:00)
A tuple in Python is immutable, are tuples in F# immutable as well? Also, if you've got two tuples both of the same type but different lengths - does it allow the comparison and if not, why not? From my point of view, if they are different lengths - it simply means they are not equivalent but it should allow the comparison?
Saturday, January 19, 2008 9:39:31 AM (Eastern Standard Time, UTC-05:00)
F# tuples are immutable. In fact, all variables are immutable unless declared otherwise. Consider this statement:

let pair = 37, 5;;

The tuple itself is immutable. That is, I can't change the values inside of it. In addition, "pair" is immutable. It can't be assigned to another tuple.

Tuples of differing lengths cannot be compared because they are actually realizations of two different generic types. "pair" above is a realization of the type Tuple<'a,'b>. A tuple of three values would be a realization of the type Tuple<'a,'b,'c>. These types each have their own IComparable.CompareTo() method that assumes the current object is being compared against another object that has the same type. This decision is because F# is very much statically typed. It is not a dynamic language like python.

That said, it *is* possible to define a new operator in F# that would handle such a case:


let inline (<!) x y =
match x, y with
| (x1,_),(y1,_,_) when x1 < y1 -> true
| (x1,_),(y1,_,_) when x1 > y1 -> false
| (_,x2),(_,y2,_) when x2 < y2 -> true
| (_,x2),(_,y2,_) when x2 > y2 -> false
| _ -> true


Now code like this could be written:

(0, 1) <! (0, 1, 2)

Useful? Maybe not. But possible. :-)
Tuesday, March 04, 2008 11:36:37 AM (Eastern Standard Time, UTC-05:00)
I know a good way to end this stupid "too-pull" versus "tuh-pull" nonsense once and for all:

When was the last time you heard someone (on either side of the pond) pronounce the word "quadruple" as "quad-ruh-pull". I know I've never heard that. Yes, you say "quintuplet" as "quin-tuh-plet", but then, that's a different form of the word tuple anyways.
Brent Schooley
Comments are closed.