Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# language - hints for newbie [closed]

Tags:

f#

Looks like here in StackOveflow there is a group of F# enthusiasts.

I'd like to know better this language, so, apart from the functional programming theory, can you point me to the better starting points to start using the F# language? I mean, tutorials, how-tos, but first of all working samples to have the chance to start doing something and enjoy the language.

Thanks a lot

Andrea

like image 706
ila Avatar asked Aug 30 '08 19:08

ila


2 Answers

Not to whore myself horribly but I wrote a couple F# overview posts on my blog here and here. Chris Smith (guy on the F# team at MS) has an article called 'F# in 20 minutes' - part 1 and part 2.

Note you have to be careful as the latest CTP of F# (version 1.9.6.0) has some seriously breaking changes compared to previous versions, so some examples/tutorials out there might not work without modification.

Here's a quick run-down of some cool stuff, maybe I can give you a few hints here myself which are clearly very brief and probably not great but hopefully gives you something to play with!:-

First note - most examples on the internet will assume 'lightweight syntax' is turned on. To achieve this use the following line of code:-

#light

This prevents you from having to insert certain keywords that are present for OCaml compatibility and also having to terminate each line with semicolons. Note that using this syntax means indentation defines scope. This will become clear in later examples, all of which rely on lightweight syntax being switched on.

If you're using the interactive mode you have to terminate all statements with double semi-colons, for example:-

  > #light;;
  > let f x y = x + y;;

  val f : int -> int -> int

  > f 1 2;;
  val it : int = 3

Note that interactive mode returns a 'val' result after each line. This gives important information about the definitions we are making, for example 'val f : int -> int -> int' indicates that a function which takes two ints returns an int.

Note that only in interactive do we need to terminate lines with semi-colons, when actually defining F# code we are free of that :-)

You define functions using the 'let' keyword. This is probably the most important keyword in all of F# and you'll be using it a lot. For example:-

let sumStuff x y = x + y
let sumStuffTuple (x, y) = x + y

We can call these functions thus:-

sumStuff 1 2
3
sumStuffTuple (1, 2)
3

Note there are two different ways of defining functions here - you can either separate parameters by whitespace or specify parameters in 'tuples' (i.e. values in parentheses separated by commas). The difference is that we can use 'partial function application' to obtain functions which take less than the required parameters using the first approach, and not with the second. E.g.:-

let sumStuff1 = sumStuff 1
sumStuff 2
3

Note we are obtaining a function from the expression 'sumStuff 1'. When we can pass around functions just as easily as data that is referred to as the language having 'first class functions', this is a fundamental part of any functional language such as F#.

Pattern matching is pretty darn cool, it's basically like a switch statement on steroids (yeah I nicked that phrase from another F#-ist :-). You can do stuff like:-

let someThing x =
  match x with
    | 0 -> "zero"
    | 1 -> "one"
    | 2 -> "two"
    | x when x < 0 -> "negative = " + x.ToString()
    | _ when x%2 = 0 -> "greater than two but even"
    | _ -> "greater than two but odd"

Note we use the '_' symbol when we want to match on something but the expression we are returning does not depend on the input.

We can abbreviate pattern matching using if, elif, and else statements as required:-

let negEvenOdd x = if x < 0 then "neg" elif x % 2 = 0 then "even" else "odd"

F# lists (which are implemented as linked lists underneath) can be manipulated thus:-

let l1 = [1;2;3]
l1.[0]
1

let l2 = [1 .. 10]
List.length l2
10

let squares = [for i in 1..10 -> i * i]
squares
[1; 4; 9; 16; 25; 36; 49; 64; 81; 100]

let square x = x * x;;
let squares2 = List.map square [1..10]
squares2
[1; 4; 9; 16; 25; 36; 49; 64; 81; 100]

let evenSquares = List.filter (fun x -> x % 2 = 0) squares
evenSqares
[4; 16; 36; 64; 100]

Note the List.map function 'maps' the square function on to the list from 1 to 10, i.e. applies the function to each element. List.filter 'filters' a list by only returning values in the list that pass the predicate function provided. Also note the 'fun x -> f' syntax - this is the F# lambda.

Note that throughout we have not defined any types - the F# compiler/interpreter 'infers' types, i.e. works out what you want from usage. For example:-

let f x = "hi " + x

Here the compiler/interpreter will determine x is a string since you're performing an operation which requires x to be a string. It also determines the return type will be string as well.

When there is ambiguity the compiler makes assumptions, for example:-

let f x y = x + y

Here x and y could be a number of types, but the compiler defaults to int. If you want to define types you can using type annotation:-

let f (x:string) y = x + y

Also note that we have had to enclose x:string in parentheses, we often have to do this to separate parts of a function definition.

Two really useful and heavily used operators in F# are the pipe forward and function composition operators |> and >> respectively.

We define |> thus:-

let (|>) x f = f x

Note that you can define operators in F#, this is pretty cool :-).

This allows you to write things in a clearer way, e.g.:-

[1..10] |> List.map (fun x -> x * x) |> List.filter (fun x -> x % 2 = 0)

Will allow you to obtain the first 10 even squares. That is clearer than:-

List.filter (fun x -> x % 2 = 0) (List.map (fun x -> x * x) [1..10])

Well, at least I think so :-)

Function composition defined by the >> operator is defined as follows:-

let (>>) f g x = g(f(x))

I.e. you forward-pipe an operation only the parameter of the first function remains unspecified. This is useful as you can do the following:-

let mapFilter = List.map (fun x -> x * x) >> List.filter (fun x -> x % 2 = 0)

Here mapFilter will accept a list an input and return the list filtered as before. It's an abbreviated version of:-

let mapFilter = l |> List.map (fun x -> x * x) |> List.filter (fun x -> x % 2 = 0)

If we want to write recursive functions we have to define the function as recursive by placing 'rec' after the let. Examples below.

Some cool stuff:-

Factorial

let rec fact x = if x <= 1 then 1 else x * fact (x-1)

nth Fibonacci Number

let rec fib n = if n <= 1 then n else fib (n-1) + fib (n-2)

FizzBuzz

let (/%) x y = x % y = 0
let fb = function
  | x when x /% 15 -> "FizzBuzz"
  | x when x /% 3  -> "Fizz"
  | x when x /% 5  -> "Buzz"
  | x              -> x.ToString()

[1..100] |> List.map (fb >> printfn "%s")

Anyway that's a very brief overview, hopefully it helps a little!!

like image 132
ljs Avatar answered Sep 24 '22 01:09

ljs


Without doubt, you should purchase Don Syme's excellent book "Expert F#". The book is very well written and is suitable for both beginners and experts alike. In it, you'll find both introductory material and much more challenging material too. At nearly 600 pages it is good value for money.

I found that it taught me a lot of useful techniques for writing more functional C# as well as providing all the reference material I needed to get started writing Windows hosted F# applications.

The book is published by Apress and has an accompanying web site at: http://www.expert-fsharp.com/default.aspx

like image 29
vextasy Avatar answered Sep 26 '22 01:09

vextasy