Friday, April 15, 2016

F# resources; Currying

interesting course: F# Fundamentals | Pluralsight

fsharp-cheatsheet @ GitHub

Home | F# for fun and profit

F# Software Foundation (fsharp.org)

Try F#

F# Workshop

F# Programming - Wikibooks, open books for an open world



F# language has an interesting feature called currying. 
Curry is a spice from India region, as well as a tree whose leaves a used a spice.

Curry - Wikipedia, the free encyclopedia Curry tree - Wikipedia, the free encyclopedia
  Curry Trees.jpg
"Red roast duck curry (hot and spicy) from Thailand"

Curry leaves are in a sequence, one by one, same as F# function arguments.
But that is not a reason why the currying feature is named...

Currying | F# for fun and profit
"Breaking multi-parameter functions into smaller one-parameter functions

...if a mathematical function can only have one parameter, then how is it possible that an F# function can have more than one? The answer is quite simple: a function with multiple parameters is rewritten as a series of new functions, each with only one parameter. And this is done automatically by the compiler for you. It is called "currying", after Haskell Curry, a mathematician who was an important influence on the development of functional programming."



To see how this works in practice, let’s use a very basic example that prints two numbers:
//normal version
let printTwoParameters x y = 
   printfn "x=%i y=%i" x y
Internally, the compiler rewrites it as something more like:
//explicitly curried version
let printTwoParameters x  =    // only one parameter!
   let subFunction y = 
      printfn "x=%i y=%i" x y  // new function with one param
   subFunction                 // return the subfunction

// example: function: distance (x, y) { return Math.Abs(x - y); }
let distance x y = x - y |> abs
// val distance : x:int -> y:int => int
distance 5 2
3
is equivalent to:
(distance 5) 2
or:
let distance5 = distance 5 // a new function with one argument
// val distance5 : (int -> int)
distance5 2
// val it : int = 3

Functions as First-Class Values (F#)

Prefix vs Infix Functions:
(+) 1 3
is equivalent to: 
1 + 3 

// function that adds 1 to its argument:
let add1 = (+) 1
// val add1 : (int -> int)

Infix functions can help make expressions more readable, i.e.:
1 + 2 + 3
// is same as
(1 + 2) + 3
// is same as
((+) ((+) 1 2) 3)
// "associative" if order of applying arguments does not change result
(1 + 2) + 3 == 1 + (2 + 3)
// "non-associative"
(36 / 6) / 2 != 36 / (6 / 2)
// same example in Lisp / Clojure
// (+ (+ 1 2) 3)

// infix function must use symbols; distance function equivalent:
let (|><|) x y = x - y |> abs
// usage:
5 |><| 2
// val it : int = 3

5 |><| 2 |><| 10
// val it : int 7

Lambda Expressions (anonymous functions):
(fun x -> x * x)
usage as a function argument to another function; lambda is symbol ->
List.map (fun x -> x * x) [1;2;3]
// distance function
(fun x y -> x - y |> abs) 5 3



Recursion:
let rec length = function // no-name argument is immediately passed to matching
    | [] -> 0 // if argument is an empty list
    | x::xs -> 1 + length xs // else x: head of list; xs: tail of list

let rec factorial n =
    if n < 2 then 1
else
    n * factorial (n - 1)


Pipe Operators:
sin 2.
is equivalent to:
2. |> sin
"pipe" operators simplify "chaining" functions  
2. |> sin |> ((*) 3)  // == sin(2) * 3
pipe operator can be in both direction, this is same as above
sin <| 2. 

pipe operator can be combined:
min 12 7
is equivalent to:
12 |> min <| 7
is equivalent to (multiple arguments, double pipe operator):
(12,7) ||> min 

Function composition:
let minus1 x = x - 1
let times2 x = x * 2
is equivalent to:
let minus1 = (+) -1  // !! not the same as (-) 1
let times2 = (*) 2

times2 (minus1 9)
is equivalent to:
(times2 << minus1) 9
is equivalent to:
times2 << minus1 <| 9
is equivalent to:
let minus1times2 = times2 << minus1
minus1times2 9
is equivalent to:
let minus1times2 = minus1 >> times2 
minus1times2 9






No comments: