// Examples from chapter 1 "Introduction" of the book // F# for Scientists // // (C) Flying Frog Consultancy Ltd., 2007 #light #r @"C:\Program Files\FSharp-1.9.6.2\bin\FSharp.PowerPack.dll" /// 1 module Introduction = /// 1.4.1.1 module BasicTypes = print_newline () 3 5.0 1 * 2 + 2 * 3 1.0 * 2.0 + 2.0 * 3.0 // A type error: //2 * 2.0 2 * int 2.0 "Hello world!".[4] "Hello " + "world!" 1 < 3 && 2.5 < 3.7 /// 1.4.1.2 module VariablesAndFunctions = let a1 = 2 ( let a = 3 in a * a ) a1 let a2 = 5 let a3 = a2 * a2 a3 * a3 let sqr1 n = n * n sqr1 5 let sqr2 (x: float) = x * x let sqr3 x : float = x * x /// 1.4.1.3 module ProductTypes = (1, 2, 3) type vec2 = { x: float; y: float } let zero1 = { x = 0.0; y = 0.0 } let zero2 = { y = 0.0; x = 0.0 } zero2.x let x_axis = { zero2 with x = 1.0 } x_axis /// 1.4.1.4 module SumTypes = type button1 = | On | Off On Off type button2 = | On of int * string | Off On (1, "mine") On (2, "hers") Off type binary_tree = | Leaf | Node of binary_tree * binary_tree Node (Node (Leaf, Leaf), Leaf) /// 1.4.1.5 module Generics = let swap(a, b) = (b, a) type 'a vec = { x: 'a; y: 'a } { x = 3.0; y = 4.0 } type 'a option = | None | Some of 'a None Some 3 /// 1.4.1.6 module ListsAndArrays = [1; 2; 3] [|1; 2; 3|] 1 :: [2; 3] [|3; 5; 7|].[1] /// 1.4.1.7 module IfExpression = let f1 x = if x < 3 then print_endline "Less than three" f1 5 f1 1 let f2 x = if x < 3 then "Less" else "Greater" f2 1 f2 5 /// 1.4.1.8 module MoreAboutFunctions = fun x -> x * x (fun x -> x * x) 2 let sqr = fun x -> x * x let ipow3 x = let sqr x = x * x x * sqr x let a, b = 3, 4 let ipow4 x = let sqr x = x * x sqr(sqr x) module Combined = let ipow3, ipow4 = let sqr x = x * x (fun x -> x * sqr x), (fun x -> sqr(sqr x)) let rec ipow n m = if m = 0 then 1 else n * ipow n (m - 1) ipow 2 16 /// 1.4.2 module PatternMatching = let f i = match i with | 0 -> "Zero" | 3 -> "Three" | _ -> "Neither zero nor three" f 0 f 1 f (1 + 2) let is_empty_list1 list = list = [] let is_empty_list2 list = match list with | [] -> true | _::_ -> false let is_empty_list3 = function | [] -> true | _::_ -> false /// 1.4.2.1 module VariablesInPatterns = let f = function | None -> 0 | Some x -> x f None f (Some 3) /// 1.4.2.2 module NamedSubpatterns = let rec pairs = function | h1::(h2::_ as t) -> (h1, h2) :: pairs t | [] | _::_ -> [] pairs [1 .. 5] /// 1.4.2.3 module GuardedPatterns = let rec positive = function | [] -> [] | h::t when h<0 -> positive t | h::t -> h::positive t positive [-3; 1; -2; 4] /// 1.4.2.4 module OrPatterns = let is_sign = function | -1 | 0 | 1 -> true | _ -> false /// 1.4.2.5 module ErroneousPatterns = (* let product a b = match a, b with | a, 0 | 0, b -> 0 | a, b -> a * b *) let product a b = match a, b with | _, 0 | 0, _ -> 0 | a, b -> a * b let extract = function | Some x -> x extract (Some 3) extract None /// 1.4.2.6 module GoodStyle = let sign1 = function | i when i < 0.0 -> -1 | 0.0 -> 0 | i when i > 0.0 -> 1 let sign2 = function | i when i < 0.0 -> -1 | 0.0 -> 0 | _ -> 1 let product a b = match a, b with | a, b -> a * b | _, 0 | 0, _ -> 0 type number1 = | Integer of int | Real of float module Bad1 = let is_zero = function | Integer 0 | Real 0.0 -> true | _ -> false is_zero (Integer -1) is_zero (Integer 0) is_zero (Real 0.0) is_zero (Real 2.6) module Good1 = let is_zero = function | Integer 0 | Real 0.0 -> true | Integer _ | Real _ -> false type number2 = | Integer of int | Real of float | Complex of float * float module Bad2 = let is_zero = function | Integer 0 | Real 0.0 -> true | _ -> false is_zero (Complex (0.0, 0.0)) module Good2 = let is_zero = function | Integer 0 | Real 0.0 -> true | Integer _ | Real _ -> false let is_zero = function | Integer 0 | Real 0.0 | Complex(0.0, 0.0) -> true | Integer _ | Real _ | Complex _ -> false is_zero (Complex (0.0, 0.0)) /// 1.4.2.7 module ParallelPatternMatching = module Unwound = let unbox3 a b c = match a with | Some a -> (match b with | Some b -> (match c with | Some c -> Some(a, b, c) | None -> None) | None -> None) | _ -> None unbox3 (Some 1) (Some 2) (Some 3) let unbox3 a b c = match a, b, c with | Some a, Some b, Some c -> Some (a, b, c) | _ -> None unbox3 (Some 1) (Some 2) (Some 3) /// 1.4.2.8 module ActivePatterns = let (|Less|Equal|Greater|) = function | c when c < 0 -> Less | 0 -> Equal | _ -> Greater /// 1.4.3 module Equality = 3 - 1 = 2 (2, 3) = (3, 4) let a = 1, 2 let b = 1, 2 // The physical equality and inequality operators have since been // removed from F#: //a == a a = b //#nowarn "62" //a == b /// 1.4.4 module SequenceExpressions = seq {1 .. 5} [1 .. 5] [|1 .. 5|] seq {0 .. 3 .. 9} // Note: these examples no longer works as of F# 1.9.6.2 //seq { for Some i in [Some 1; Some 3; None; Some 2] -> // i * i } //let xs = [Some 1; Some 3; None; Some 2] //seq { for Some i in [Some 1; Some 3; None; Some 2] when i < 3 -> // i * i } // The following construct is deprecated: [ for x in 1 .. 3 for y in 1 .. 3 -> x, y ] /// 1.4.5 module Exceptions = try raise (Failure "My problem") with Failure s -> s exception ZeroLength let norm (x, y) = match sqrt(x * x + y * y) with | 0.0 -> raise ZeroLength | s -> x / s, y / s norm (3.0, 4.0) norm (0.0, 0.0) let safe_norm r = try norm r with | ZeroLength -> 0.0, 0.0 safe_norm (3.0, 4.0) safe_norm (0.0, 0.0) /// 1.5 module ImperativeProgramming = type vec2 = { mutable x: float; mutable y: float } let r = { x = 1.0; y = 2.0 } r.x <- 3.0 r let a = ref 2 !a a := 3 incr a !a let x = ref 5 while !x > 0 do decr x !x /// 1.6 module FunctionalProgramming = let a = [1; 2; 3] let b = 0::a a, b /// 1.6.2 module Recursion = module ImperativeExample = let factorial n = let accu = ref 1 for i = 1 to n do accu := i * !accu !accu factorial 5 let rec factorial = function | 0 -> 1 | n -> n * factorial (n - 1) factorial 5 /// 1.6.3 module Currying = let rec ipow_1(x, n) = match n with | 0 -> 1.0 | n -> x * ipow_1(x, n - 1) let rec ipow_2 n x = match n with | 0 -> 1.0 | n -> x * ipow_2 (n - 1) x let square = ipow_2 2 square 5.0 let cube = ipow_2 3 cube 3.0 fun x -> ipow_1(x, 2) ipow_2 2 /// 1.6.4 module HigherOrderFunctions = let d f x = // OCaml's epsilon_float is being deprecated but there is no // clear replacement and .NET does not provide this value. let dx = sqrt epsilon_float (f (x + dx) - f (x - dx)) / (2.0 * dx) let f x = x ** 3.0 - x - 1.0 d f 2.0 let f' = d f f' 2.0