Type inference in F#

I have recently been to a short F# presentation at HiQ in Arboga. One of the things that got mentioned was type inference. Both Visual Basic and C# have type inference in their current version, but F# takes this one step further. This approach will produce two integers in VB when Option Infer is set to On:

Dim X = 10
Dim Y = 20

This is the F# version of the above code:

let mutable x=10
let mutable y=20

But when it comes to function declarations, VB is not support type inference anymore. This will not compile:

Private Function DoSomething(ByVal X, ByVal Y)
   Return X
End Function

You will need to declare the input types and the return type, like so:

Private Function DoSomething(ByVal X As Integer, ByVal Y As _
   Integer) As Integer
   Return X
End Function

In F#, type inference will work all the way. This is the F# version of the DoSomething function, with type inference:

let DoSomething x y = x

The DoSomething function can be called using any arguments. Type inference will take care of the argument and return typing. Once the function is called, the compiler knows what types the function will handle. Therefore, you can call the function using strings or integers but not a combination. Here, z1 will be a string and z2 will be an integer. This is the complete code listing:

let mutable x=10
let mutable y=20

let DoSomething x y = x
let z1 = DoSomething "winsoft" "rocks"
let z2 = DoSomething 10 20

Now, this is strange: If the types interact with each other, the first call will determine the types of the input and output. If I change my code, so that the function DoSomething returns x + y, only the first call will be accepted.

let mutable x=10
let mutable y=20

let DoSomething x y = x + y
let z1 = DoSomething "winsoft" "rocks"
//let z2 = DoSomething 10 20

The second call will fail, because the compiler in this case only provides a string version of the DoSomething function.

Tuples

Tuples in F# is a list of objects with different types, and the tuple itself is strongly typed. You can imagine a simple class or a structure without having to declare the type. This code creates a tuple called myTuple that contains a string, and integer, another string and finally a boolean.

let myTuple=("A", 10, "B", true)

The string representation of a tuple is a string representation of the individual values within parenthesis. This code…

let myTuple=("A", 10, "B", true)
System.Console.WriteLine(myTuple)

…gives you…

(A, 10, B, True)

This code will extract the individual values from the tuple. The output from this code will be 10.

let myTuple=("A", 10, "B", true)
let v1, v2, v3, v4 = myTuple
System.Console.WriteLine(v2)

The types of the values will be the .NET types from the original values in the tuple, v1 is a string, v2 is a 32 bit integer, v3 is also a string and v4 is a boolean. Tuples can be used in many ways, as allowing a single function to return multiple values.

F# functions

Functions are declared using the let keyword, followed by a name, a parameter list and a definition.

This creates a function that adds to values and returns the result (first line). The two middle lines calls the function.

let myFunction x y = x + y

let result1 = myFunction 10 20
let result2 = myFunction 15 25

printfn "%d %d" result1 result2

The last line prints the result to the screen. It should be 30 40.

To specify the type of a parameter, you encapsulate it in parentheses, together with the type name. In this example, only the first parameter has a given type:

let myFunction (x:int) y = x + y

To specify the return type, add a colon followed by a type name. The following function divides a value in three. The first line is the function declaration, the second line is a call (note that I cast a int constant to a float), and the third line prints the result to the screen.

let divInThree (t:float) = t / (float)3 : float
let result = divInThree ((float)18)
printfn "%f" result

The result should be 6.

Conditions and iterations in F#

Conditions
This code will first assign a value to a and b, and print the values out. Thereafter, it will assign a value to c, that depends on the value of a. The value will be 20. Finally, it will print out both a, b and c.
A programmer at NASA.

let a=1
let b=2
printfn "%d %d" a b

let c=
if a=0 then 10
elif a=1 then 20
else 30

printfn "%d %d %d" a b c

Iterations
This code will print eleven numbers on screen, from 10 to 20:

for x in 10..20 do printfn "%d" x

Unlike Visual Basic and C#, indentations actually means something in F#. Look at this iteration. The output is one two one two one two:

for x in 1..3 do
printfn "one"
printfn "two"

But just by changing the indentation (removing the indentation before the second prinfn), the output is changed to one one one two. The second printfn is no longer a part of the iteration.

for x in 1..3 do
printfn "one"
printfn "two"

You can also do while-iterations, that is, iterations that executes while a condition is true.

Using the framework from F#

Just by typing the open statement, you can use the .NET Framework, or any other referenced libraries. To access the Console type, just add the following line to your source code:

open System

This program uses the built-in library function printfn, and then the WriteLine function to write “Hello world” to the screen.

printfn "Hello world"
open System
Console.WriteLine("Hello world")

So, displaying a message box, is just a matter of adding a reference to System.Windows.Forms, and this is how it could be done:

let x=System.Windows.Forms.MessageBox.Show("Hello world")

Or like so:

open System.Windows
let y=Forms.MessageBox.Show("Hello world")

Or even:

open System.Windows.Forms
let z=MessageBox.Show("Hello world")

Things to know about F# before getting started and mutable variables

F# is a .NET enabled functional programming language that has features that you would expect such a language to have (lists, tuples, pattern matching and so on), as well as the features you would expect from a .NET language such as preemptive multitasking, dynamic linking and Unicode strings. The program starts from the top of your source file instead of in a main function (as C# or Visual Basic), and the language is case sensitive, like C#. The editor support in Visual Studio 2008 slightly more limited than for C# or Visual Basic; you can still work with breakpoints and the locals window but perhaps not with code suggestions or code tips.
This example creates an integer, initialized with the value 10, and prints it out:

let x = 10
printfn "x=%d" x

If I wanted to assign a new value to x like below (complete source is shown, not just changes), a compile error will occur, telling me that x is not mutable – it can not change it’s value.

let x=10
printfn "x=%d" x
x <- 11
printfn "x=%d" x

The keyword mutable at declaration, gives x the capability to chainge.

let mutable x=10
printfn "x=%d" x
x <- 11
printfn "x=%d" x

F# and PhotoName

I have just decided to look in to F#, the new functional .NET language by Microsoft. It installs with Visual Studio 2010, and it can be installed for Visual Studio 9. I use Visual Studio 9 for my everyday work, so I installed it from here (click on the word MSI in the first paragraph under “F# Compiler versions”). After installation, a couple of new project templates are available, including a good tutorial. Thanks for that, Microsoft!

And now for something less positive. I got a comment today on PhotoName on a never-do-this-thing in my source code. I was storing values in the registry under HKEY_LOCAL_MACHINE, something that you might want to do in an installation process, but never in an installed program. Back in the Windows 2000 days (or even XP), I thought of the Local Machine hive key as an alternative to the Current User hive key, with bigger scope. This is not good practice, and by default in Vista, Windows prevents programs from doing this. This is good, of course, and bringing this old mistake up to the surface, so that it could be fixed. I am a Vista user myself, but I actually use PhotoName on an old XP machine, so I am very thankful that this issue was brought up, so that I could update my code. If you have an older project, that you develop on a XP machine, you should make sure that you’re not using Application.CommonAppDataRegistry.SetValue but Application.UserAppDataRegistry.SetValue instead.

If you have an older version of PhotoName installed, uninstall it from the Control Panel before installing the new version.