Experience With F#

Hesamyan
4 min readMar 3, 2021

Here I am going to share my experience with F# — the functional-first, general-purpose, strongly typed, multi-paradigm programming language — which I have recently started to learn.

Photo by James Harrison on Unsplash

This programming language encompasses functional, imperative, and also object-oriented programming methods nevertheless, its functional approach weighs the most.

In brief, I am going to explain the following titles

Pipelines

One of the aspects of any Functional programming is its ability to chaining a bunch of functions in a line to make the output of one function as the input of another function. However, it is also possible for none functional programming languages to do like that, but the difference is the simplicity and clarity achieved by using pipeline.

The pipelines are exactly the same as pipelines ‘|’ in the Unix-like terminals, but in F# by introducing these formats of pipelines ‘|>’ and ‘<|’ that in turn, these elaborated pipelines can also imply which direction they spit out their output.

Note that if the function has multiple arguments, the piped argument will seat in the last position among all arguments.

let sumDown n =
Array.ofSeq [1..n]
|> Array.map (fun ele -> ele * ele)
|> Array.fold (fun accu ele -> accu + ele) 0

Matching input

Even though this functionality works to some extent similar to ‘switch’ in C-like programming languages, it is more capable of the ‘switch’. To just show one difference, in each case we can add a ‘when’ keyword to make it conditional or an ‘if’ statement to make our filter even narrower. The syntax is like following:

let filter x =     
match x with
| 1
| 2
| 3 -> printfn "Found 1, 2, or 3!"
| x ->
if x % 2 = 0 then
printfn "Found Even number greater than 3!"
else
printfn "Out of the bound!"

With ‘when’ statement:

let detectValue point target =
match point with
| (a, b) when a = target && b = target ->
printfn "Both values match target %d." target
| (a, b) when a = target ->
printfn "First value matched target in (%d, %d)" target b
| (a, b) when b = target ->
printfn "Second value matched target in (%d, %d)" a target
| _ ->
printfn "Neither value matches target."

Unpacking Lists

This functionality unpacks any List into two parts — ‘X :: XS’ the X or Head part and the XS or the Tail part. The first segment is in fact the first item of type of the provided Enumerable and the second segment is the entire Enumerable excluding the first item. The syntax is like follows:

let rec sum list =
match list with
| head :: tail -> head + sum tail
| [] -> 0

Wildcard In Matching

As its name suggests, the wildcard “_” acts for catching any other possible unmentioned items inside the Matching, exactly serves as the ‘default’ option inside the ‘switch’ in all C-like programming languages. The syntax of its usage goes as following:

let filter input =
match input with
| 1
| 2
| 3 -> printfn "%i" input
| _ -> printfn "Greater than 3"

Types

In F# we can define our type which has its particular notion in each context, including declaring a class, record, structure, discriminated union, enumeration type, unit of measure, or type abbreviation. The syntax of each usage showed as follows:

By defining a new Class:

type MyClass(x: int, y: int) =
do printfn "%d %d" x y
new() = MyClass(0, 0)

Or by defining a Record type:

type Point = { X: float; Y: float; Z: float; }

Or by defining a Structure (note that it is possible to use the ‘Struct’ attribute):

type StructPoint1 =
struct
val x: float
val y: float
val z: float
end
// or[<Struct>]
type StructPoint2 =
{ X: float
Y: float
Z: float }

Or by defining a Discriminal Union:

type Shape =
| Rectangle of width : float * length : float
| Circle of radius : float
| Prism of width : float * float * height : float

Or by defining Enumeration

type Color =
| Red = 0
| Green = 1
| Blue = 2

Or by type abbreviation

type SizeType = uint32

And finally by defining the Unit of Measures:

[<Measure>] type ml = cm^3

Active Patterns

Active patterns help us to define distinct names that divide our input in a way that we can use it in a pattern matching expression.

let (|Even|Odd|) input = if input % 2 = 0 then Even else Odd

Or this a bit complicated one which used ‘_’ and Regex to filter out the input

let (|Regex|_|) pattern input =
let m = Regex.Match (input, pattern)
if m.Success then
List.tail [ for g in m.Groups -> g.Value ] |> Some
else
None

And here you can find a sample of usage of the first active pattern in action:

let TestNumber input =    
match input with
| Even -> printfn "%d is even" input
| Odd -> printfn "%d is odd" input

Modules

When we have several interrelated functions which most of the time are correlated to a specific type, for the sake of making our cleaner we better use these option which gathers all of the functions under the module. For invoking the functions we just need to mention the module name preceded the function name.

module MyModule1 =
let module1Value = 100
let module1Function x =
x + 10

module MyModule2 =
let module2Value = 121
let module2Function x =
x * (MyModule1.module1Function module2Value)

Thank you.

--

--