Today I was speaking with a colleague about some F#, and he pointed out a few gotchas with F# type signatures, especially if you’ve spent some time with Haskell (and not OCaml or other ML-ish language).
->style function signatures please let me know.
The example we were looking at is
Seq.unfold, whose signature looks like this:
Apostrophes for type parameters
Any type prefixed with a
' character represents a type parameter (or generic type in C# parlance). For
unfold this means
'T can be any type. We can also write this in potentially more familiar .NET syntax:
A lot of the F# code I see follows a more Haskellish (?) convention of using lowercase type variable names, more like:
Asterisk for tuples
Types separated by a
* are tupled (or product types, which explains the
* symbol). For example,
(1, "abc", Foo()) is of type
int * string * Foo.
'T * 'State represents a tuple of
Postfix generic syntax
F# supports both .NET-style prefix generic syntax and ML-style postfix syntax. So instead of writing
int option, we can also write
Option<int> (both forms are equivalent). Which means we can re-write
With those things in mind, let’s use the
unfold signature to work out what it does.
Given a function that can take
's values and return a tuple of an element and next
's value or nothing, and a starting
unfold will generate a sequence of
't values until the generator function returns
None (i.e. potentially infinite).
We could use this to generate a sequence of all the days since a starting date (infinite, at least until
Translating to other languages
Finally, if you’re more familiar with C# or Haskell, here are my attempted translations:
Haskell uses lowercase type names for generics (instead of
' characters), while concrete types have uppercase names. It also uses the same syntax for tuple types as values, so
(1,2) :: (Int, Int). For some odd reason, Haskell uses
:: for “type of” instead of a single
The C# version is a bit messier due to having to use
Func instead of a shorthand for function types, and similarly for declaring tuple types. (I’ve also uncurried the C# version otherwise we end up with nested
Func types everywhere, and it is the more typical form for C# functions.)