1

As a F# newbie, I am having problems with understanding the term "Lifting" and I can not properly lift a function.

For example how can I lift the below function and how it will effect the functions behavior.

let add item element = item :: element

Any help would be appreciated.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Tartar
  • 5,149
  • 16
  • 63
  • 104

1 Answers1

7

Check out this page http://fsharpforfunandprofit.com/posts/elevated-world/ it has the best explanations with graphical representations of the idea of lifting.

The site is a treasure trove of good material for understanding F# in particular and functional programming in general.

In simple terms, the idea of lifting refers to taking a function f that works with a simple type and creating a new version liftedF that works with a generic type. How do we do this? We take the function f pass it to another function and it returns a "new and improved" version of f. For instance say you have a simple function that returns the square of an integer:

let square x = x * x    // val square : int -> int

Simple right? You pass an int and it returns another int.

Now lets create a new version like this:

let squareArray xA = Array.map square xA  // val squareArray : int [] -> int []

Wow! squareArray can square a whole array of integers and it was so easy to create! All I needed to do is pass square to Array.map.

Look at the signatures square is int -> int and squareArray is int [] -> int []. That is lifting!

If you look at the signature of Array.map is ('a -> 'b) -> 'a [] -> 'b [] which can be interpreted as receiving a function from type 'a to 'b and an array of 'as and returning an array of 'bs. But it can also be interpreted as receiving a function from 'a to 'b'and returning a lifted function from 'a[] to 'b[]:

  • ('a -> 'b) -> 'a [] -> 'b [] is the same as
  • ('a -> 'b) -> ('a [] -> 'b [])

You can lift functions to any generic types. What is a generic type? It is a type that has another type as a parameter, there are many generic types that you probably already know:

  • List<'t> (also expressed as 't list) is generic because you can have lists of different types like List<int>, List<string>, List<int * string>, ...
  • Array<'t> : Array<int>, Array<string>, Array<int * string>, ...
  • Option<'t> : Option<int>, Option<string>, Option<int * string>, ...
  • Result<'t,'r> : Result<int, string>, Result<string, string>, ...

You can lift functions to other generic types:

let squareOption xO = Option.map square xO  // val squareOption : int option -> int option
let stringArray  sL = Array.map  string sL  // val stringArray : int [] -> string []

It is all in the function signatures. We can take a function from...

  • int -> int and get a List<int> -> List<int> function
  • ... or from int -> int to Option<int> -> Option<int>
  • ... or from string -> float to string [] -> float[]
AMieres
  • 4,944
  • 1
  • 14
  • 19