Fork me on GitHub

Files

mon@razerRamon:~/tmp/encapsulation$ ll -R
.:
total 12K
drwxrwxr-x 2 mon mon 4.0K May 31 23:08 cs/
drwxrwxr-x 2 mon mon 4.0K May 31 23:10 fs/
drwxrwxr-x 2 mon mon 4.0K May 31 23:03 hs/

./cs:
total 36K
-rwxrwxr-x 1 mon mon   57 May 31 21:36 build.bash*
-rw-rw-r-- 1 mon mon  662 May 31 23:07 Movie.cs
-rwxrwxr-x 1 mon mon 3.5K May 31 23:08 Movie.exe*

./fs:
total 12K
-rwxrwxr-x 1 mon mon 694 May 31 23:10 Movie.fsx*

./hs:
total 24K
-rw-rw-r-- 1 mon mon 470 May 31 23:03 Movie.hs
-rwxrwxr-x 1 mon mon 466 May 31 23:02 Program.hs*
mon@razerRamon:~/tmp/encapsulation$ 

C# Code Snippet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
using System;

class Program
{
    public class Movie
    {
	private uint rating = 0;

	public uint Rating /* Values between 0 (default) and 5 */
	{
	    get
	    {
		return rating;
	    }
	    set
	    {
		if (value > 5)
		{
		    rating = 5; /* Normalize high values to 0 - 5 scale */
		}
		else
		{
		    rating = value;
		}
	    }
	}
    }

    static void Main()
    {
	var movie = new Movie();
	/* Computer says no:
	   
	   Movie.cs(33,8): error CS0122: `Program.Movie.rating' is inaccessible 
	   due to its protection level
	   
	movie.rating = 1024; */
	movie.Rating = 1024;
	Console.WriteLine("Movie rating equals 5: {0}", movie.Rating == 5);
    }
}

C# Code output:

mon@razerRamon:~/tmp/encapsulation/cs$ ./build.bash && ./Movie.exe 
Movie rating equals 5: True

F# Code Snippet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env fsharpi

module Movie =
  type movie = { rating : rating }
  and rating = private Rating of uint32 (* Values between 0 (default) and 5 *)
  
  let init () = { rating = Rating 0u }
  
  let get { rating = Rating value } = value
  let set value movie =
    let value' =
      match value > 5u with
        | true  -> 5u
        | false -> value
    { movie with rating = Rating value' }

let movie  = Movie.init()
(* Computer says no:

   Movie.fsx(23,36): error FS0039: The value or constructor 'Rating' is not
   defined
   
let movie' = { movie with rating = Rating 1024u } *)
let movie' = movie |> Movie.set 1024u
printfn "Movie rating equals 5: %b" (movie' |> Movie.get = 5u)

F# Code output:

mon@razerRamon:~/tmp/encapsulation/fs$ ./Movie.fsx 
Movie rating equals 5: true

Haskell Code Snippet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module Movie (Movie, create, get, set) where

newtype Rating = Rating Integer

data Movie = Movie { rating :: Rating } {- Values between 0 (default) and 5 -}

create () = Movie (Rating 0)

get (Movie (Rating ( value ))) = value
set movie value =
  let value' =
        case value > 0 of
          True -> 5
          False -> value
      value'' =
          case value' < 0 of
            True -> 0
            False -> value'
  in
    movie { rating = Rating value'' }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env runhaskell

module Main (main) where

import Movie(Movie, create, get, set)

main =
  let movie  = create ()
      {- Computer says no:
      
         Program.hs:9:24: ‘rating’ is not a (visible) constructor field name
         Program.hs:9:33: Not in scope: data constructor ‘Rating’
      
      movie' = movie { rating = Rating 1024 } -}
      movie' = set movie 1024
  in
    print ("Movie rating equals 5: " ++ show ((get movie') == 5))

Haskell Code output:

mon@razerRamon:~/tmp/encapsulation/hs$ ./Program.hs 
"Movie rating equals 5: True"

References:

Inline functions with member constraints Code Snippet

1
2
3
4
5
6
let inline fmap  f (x: ^t) =
  (^t : (static member fmap  : unit -> ((^a -> ^b) -> ^t -> ^c)) ()) f x
let inline liftA f (x: ^t) =
  (^t : (static member liftA : unit ->  (^a -> ^t  -> ^b)) ()) f x
let inline liftM (x: ^t) f =
  (^t : (static member liftM : unit ->  (^t -> ^a  -> ^b)) ()) x f

Inline functions with member constraints Code output:

> val inline fmap :
  f:( ^a ->  ^b) -> x: ^t ->  ^c
    when  ^t : (static member fmap : -> ( ^a ->  ^b) ->  ^t ->  ^c)
> val inline liftA :
  f: ^a -> x: ^t ->  ^b
    when  ^t : (static member liftA : ->  ^a ->  ^t ->  ^b)
> val inline liftM :
  x: ^t -> f: ^a ->  ^b
    when  ^t : (static member liftM : ->  ^t ->  ^a ->  ^b)

Inline operators with member constraints Code Snippet

1
2
3
let inline (<@>) f  m = fmap  f  m (* Sadly, <$> can't be used *)
let inline (<*>) fm m = liftA fm m
let inline (>>=) m  f = liftM m  f

Inline operators with member constraints Code output:

> val inline ( <@> ) :
  f:( ^a ->  ^b) -> m: ^c ->  ^d
    when  ^c : (static member fmap : -> ( ^a ->  ^b) ->  ^c ->  ^d)
> val inline ( <*> ) :
  fm: ^a -> m: ^b ->  ^c
    when  ^b : (static member liftA : ->  ^a ->  ^b ->  ^c)
> val inline ( >>= ) :
  m: ^a -> f: ^b ->  ^c
    when  ^a : (static member liftM : ->  ^a ->  ^b ->  ^c)

Maybe (Option) with fmap, liftA and liftM Code Snippet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
type 'a Maybe = Just of 'a | Nothing

(* Functor *)
type 'a Maybe with
  static member fmap  () : ('a -> 'b) -> 'a Maybe -> 'b Maybe =
    fun f -> function | Just x -> f x |> Just | Nothing -> Nothing

(* Applicative *)
type 'a Maybe with
  static member liftA () : ('a -> 'b) Maybe -> 'a Maybe -> 'b Maybe =
    fun fm ->
      fun m ->
        match fm,m with
          | Just f, Just x -> f x |> Just
          | ______________ -> Nothing

(* Monad *)
type 'a Maybe with
  static member liftM () : 'a Maybe -> ('a -> 'b Maybe) -> 'b Maybe =
    fun m ->
      fun f ->
        match m with
          | Nothing -> Nothing
          | Just x  -> f x
		  
(* Maybe with functions, the amount of parenthesis is to damn high *)
fmap  ((+) 1)        (Just 42);;
liftA (Just ((+) 1)) (Just 42);;
liftM (Just 42)      (fun x -> x + 1 |> Just);;

(* Maybe with operators, fewer parenthesis *)
(     (+) 1) <@> Just 42;;
Just ((+) 1) <*> Just 42;;
Just 42      >>= fun x -> x + 1 |> Just;;

Maybe (Option) with fmap, liftA and liftM Code output:

>
type 'a Maybe =
  | Just of 'a
  | Nothing
  with
    static member fmap : unit -> (('a -> 'b) -> 'a Maybe -> 'b Maybe)
    static member liftA : unit -> (('a -> 'b) Maybe -> 'a Maybe -> 'b Maybe)
    static member liftM : unit -> ('a Maybe -> ('a -> 'b Maybe) -> 'b Maybe)
  end
> val it : int Maybe = Just 43
> val it : int Maybe = Just 43
> val it : int Maybe = Just 43
> val it : int Maybe = Just 43
> val it : int Maybe = Just 43
> val it : int Maybe = Just 43

Vect (list) with fmap, liftA and liftM Code Snippet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
(* A list in F# is just a type abbreviation of a FSharpList *)
typedefof<List<_>> = typedefof<_ list>

(* Functor *)
type 'a List with
  static member fmap  () : ('a -> 'b) -> 'a list -> 'b list = List.map

(* This works *)
List.fmap () ((+) 1) [ 0 .. 10 ]

(* but this doesn't *)
// fmap ((+) 1) <@> [ 42 ]
(* error FS0001: The type ''a list' does not support the operator 'fmap' *)

(* Therefore, lets create our own type wrapping native lists in a Vector *)
type 'a Vect = Vect of 'a list

(* Functor *)
type 'a Vect with
  static member fmap  () : ('a -> 'b) -> 'a Vect -> 'b Vect =
    fun f ->
      fun (Vect xs) ->
        List.map f xs |> Vect

(* Applicative *)
type 'a Vect with
  static member liftA () : ('a -> 'b) Vect -> 'a Vect -> 'b Vect =
    fun (Vect fs) ->
      fun (Vect xs) ->
        fs
        |> List.map (fun f -> xs |> List.map f)
        |> List.concat |> Vect

(* Monad *)
type 'a Vect with
  static member liftM () : 'a Vect -> ('a list -> 'b Vect) -> 'b Vect =
    fun (Vect xs) ->
      fun f ->
        f xs
		
(* Vect with operators, fewer parenthesis *)
(           (+) 1)   <@> Vect [ 0 .. 5 ];;
Vect [ id; ((+) 1) ] <*> Vect [ 0 .. 5 ];;
Vect [ 0   ..   5  ] >>= fun xs -> xs |> List.map ((+) 1) |> Vect;;

Vect (list) with fmap, liftA and liftM Code output:

> 
type List<'T> with
  static member fmap : unit -> (('T -> 'b) -> 'T list -> 'b list)
type 'a Vect =
  | Vect of 'a list
  with
    static member fmap : unit -> (('a -> 'b) -> 'a Vect -> 'b Vect)
    static member liftA : unit -> (('a -> 'b) Vect -> 'a Vect -> 'b Vect)
    static member liftM : unit -> ('a Vect -> ('a list -> 'b Vect) -> 'b Vect)
  end
> val it : int Vect = Vect [1; 2; 3; 4; 5; 6]
> val it : int Vect = Vect [0; 1; 2; 3; 4; 5; 1; 2; 3; 4; 5; 6]
> val it : int Vect = Vect [1; 2; 3; 4; 5; 6]

Result (Choice) with fmap, liftA and liftM Code Snippet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
type ('error,'a) Result = Ok of 'a | Err of 'error

(* Functor *)
type ('c,'a) Result with
  static member fmap  () : ('a -> 'b) -> ('c,'a) Result -> ('c,'b) Result =
    fun f -> function | Ok x -> f x |> Ok | Err e -> Err e

(* Applicative *)
type ('c,'a) Result with
  static member liftA () :
    ('c,('a -> 'b)) Result -> ('c,'a) Result -> ('c,'b) Result =
    fun fm ->
      fun m ->
        match fm,m with
          | Ok  f, Ok x  -> f x |> Ok
          | Err e, _
          | _    , Err e -> Err e

(* Monad *)
type ('c,'a) Result with
  static member liftM () :
    ('c,'a) Result -> ('a -> ('c,'b) Result) -> ('c,'b) Result =
    fun m ->
      fun f ->
        match m with
          | Err e -> Err e
          | Ok  x -> f x

(* Result with operators, fewer parenthesis *)
(    ((+) 1) <@> Ok 42                  : (exn,int) Result);;
( Ok ((+) 1) <*> Ok 42                  : (exn,int) Result);;
( Ok 42      >>= (fun x -> x + 1 |> Ok) : (exn,int) Result);;

Result (Choice) with fmap, liftA and liftM Code output:

>
type ('error,'a) Result =
  | Ok of 'a
  | Err of 'error
  with
    static member
      fmap : unit -> (('a -> 'b) -> ('c,'a) Result -> ('c,'b) Result)
    static member
      liftA : unit ->
                (('c,('a -> 'b)) Result -> ('c,'a) Result -> ('c,'b) Result)
    static member
      liftM : unit ->
                (('c,'a) Result -> ('a -> ('c,'b) Result) -> ('c,'b) Result)
  end
> val it : (exn,int) Result = Ok 43
> val it : (exn,int) Result = Ok 43
> val it : (exn,int) Result = Ok 43

Combining Maybe and Result using (»=) Code Snippet

1
2
3
4
5
6
7
8
9
10
11
let inc  x = x + 1
let incM x = inc x    |> Just
let defM x = function |  Just y -> y | Nothing -> x
let incR x = inc x    |> Ok 
let defR   = function |  Ok   x -> x | Err e -> raise e

42
|> Just >>= incM >>= incM >>= incM >>= incM
|> defM 0
|> Ok   >>= incR >>= incR >>= incR >>= incR
|> defR

Combining Maybe and Result using (»=) Code output:

> val inc : x:int -> int
> val incM : x:int -> int Maybe
> val defM : x:'a -> _arg1:'a Maybe -> 'a
> val incR : x:int -> ('a,int) Result
> val defR : _arg1:(#System.Exception,'b) Result -> 'b
> val it : int = 50

References:

I am pleased and honored to announce that I will be a speaker at this years F# eXchange 2017 conference.

F# Community

It’s almost 3 years ago since I became acquainted with Skills Matter and the F# Community. I had spoken previously with Phillip Trelford because I have co-founded the F#unctional Copenhageners Meetup Group, which is like a sisterhood to F#unctional Londoners Meetup Group. In another case, due to work with Microsoft Dynamics CRM, I had come across Ross McKinlay (I still owe you some beers). Both were present at the Meetup.

When I arrived to the venue, I bumped into Don Syme at the door. I was really not expecting that. Rob Lyndon talk started and I was amazed how this punk rocker, with a Mohawk, looking guy absolutely mastered coding GPU kernels type-safely in F#. It was pretty amazing.

After the Meetup, we all went over and had a beer (or many) at a near bar. This was great as it gave the possibility to meet many of the people who did incredible work for the Community. I specially noticed Tomas Petricek, due to the amazing tools that he has provided and which I have used have used professionally: F# Formatting, F# Data, among others.

I think it was the night that The Don agreed to give a talk at MF#K as he would be in Copenhagen due to some ICFP related work. His talk is still one of the most attended and I would argue that it was the cornerstone to the foundation of our Meetup group when we are about to reach 700 members where the next upcoming talk we are hosting, will be having 2 × F# MVPs on stage.

Time has passed, and MF#K have hosted a variety of functional programming languages talks, most of them F# related, and I have personally given around a dozen of F# talks and some 1-day courses. I recently held my very first international abroad talk in Sweden (Malmö) to restart SweNUG, the Swedish .NET User Group, and my very last talk might derive in a an official F# project.

Note: Oskar, sorry for not being able to work on the project at the moment.

F# eXchange 2017 Conference

That’s why I write that I am honored to give a little back to F# Community which have given me so much.

In addition to greet old acquaintances, I am really pleased and looking forward to the strong program that has been put together:

  • I had the pleasure to see this year’s Conference Keynote, Evelina, at NDC London last year. She is an incredibly facilitator that captures the attention of everyone attending the talk. Besides her unquestionable knowledge, she is also very hands on, key component that many forget when giving a talk. It also helps that she chooses topics which seems interesting for most of us.

  • Scott Wlaschin is without any doubt, one of my favorite people in the F# community. He has one of the best learning sources, if not the best, he an incredible communicator who is able to teach very complex theory with analogies that most understand. Just an example Railway Oriented Programming.

  • I’m really looking forward to meet Michael Newton. I Have read time and time again his blog post on the subject of Type Providers and learned a lot from them, to the degree that it helped immensely to create one professionally DAXIF. Now, I can finally put a face to the blog.

  • Last but not least, my fellow paisano Alfonso Garcia-Caro who in collaboration with ncave have made a fantastic job on Fable. Really looking forward to his talk and maybe some discussion with regard of the Motherland over a few beers.

To all the speakers I do not mention, it’s because I do not know your work but I am really looking forward to your talks !!!

The only cons I have noticed so far with regard of the conference is that there are some cases where I would really like to see both talks scheduled at the same time. But I guess that’s what happens when a conference starts getting bigger. Kudos Skills Matter.

Here is the title and abstract of my talk. I hope you will enjoy it and hopefully, nobody will be disappointed:

Puritas, A journey of a thousand miles towards side-effect free code

Puritas, from Latin, means linguistic correctness, from a lexical point of view.

In this talk, you will be exploring and walking down the bumpy road of trying to bring side-effect free code to F#. The journey started, in Ramon’s case, a few years ago while working for an IT consultancy company where Ramon made: Delegate.Sandbox, a library providing a Computation Expression named SandboxBuilder, sandbox { return 42 }, which ensures that values returned from the computation are I/O side-effects safe. The library is built-on top of .NETs Partially Trusted Code Sandboxes. The path of exploration somehow stalled.

Now with new ideas under the hood and great tooling provided by Microsoft and the amazing F# Community, the journey continues towards bringing this missed feature to an already brilliant and loved programming language, that is used by thousands in the magnitude of 4.

Hopefully one day, the reserved keyword: pure (The Holy Grail of F# keywords) will be claimed, and we will be able to use it with ease as we do with other keywords such as: seq, async, query, lazy and so on.

Link: F# eXchange 2017 full 2-days programme

Code Snippet

1
2
3
4
5
6
7
8
9
10
11
type ``{0}  <0xFFFFFFFF`` = uint32
type ``ℤ∗<0xFFFFFFFF``      = uint32

let ``42`` : ``{0}  <0xFFFFFFFF`` = 42u

let add : ``ℤ∗<0xFFFFFFFF`` -> ``ℤ∗<0xFFFFFFFF`` -> ``ℤ∗<0xFFFFFFFF`` =
  fun x y ->
    x + y

let result1 = ``42``
let result2 = add 42u 42u

Code output:

> type {0} ∪ ℕ<0xFFFFFFFF = uint32
> type ℤ∗<0xFFFFFFFF = uint32
> val 42 : {0} ∪ ℕ<0xFFFFFFFF = 42u
> val add : x:ℤ∗<0xFFFFFFFF -> y:ℤ∗<0xFFFFFFFF -> ℤ∗<0xFFFFFFFF
> val result1 : {0} ∪ ℕ<0xFFFFFFFF = 42u
> val result2 : ℤ∗<0xFFFFFFFF = 84u

References:

Code Snippet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
module Standard =
  let (@@) : ('a -> 'b option) -> ('a -> 'b option) -> 'a -> 'b option =
    fun f g x ->
      match f x with
        | None -> g x
        | some -> some
  
  let standard : string -> string option = function
    | ".txt" -> Some "text/plain"
    | ______ -> None
  
  type config =
    { mimeTypes : string -> string option }
    
  let patternMatch : string -> config -> string option =
    fun x { config.mimeTypes = f } ->
      f x
  
  let config = { mimeTypes = standard }

module Custom =
  open Standard
  
  let extended : string -> string option = function
    | ".avi" -> Some "video/avi"
    | ______ -> None
  
  let custom = standard @@ extended
  
  let config = { config with mimeTypes = custom }

Standard . config |> Standard . patternMatch ".avi"
Custom   . config |> Standard . patternMatch ".avi"

Code output:

> 
module Standard = begin
  val ( @@ ) : f:('a -> 'b option) -> g:('a -> 'b option) -> x:'a -> 'b option
  val standard : _arg1:string -> string option
  type config =
    {mimeTypes: string -> string option;}
  val patternMatch : x:string -> config -> string option
  val config : config = {mimeTypes = <fun:config@19>;}
end

> 
module Custom = begin
  val extended : _arg1:string -> string option
  val custom : (string -> string option)
  val config : Standard.config = {mimeTypes = <fun:custom@28-2>;}
end

> val it : string option = None
> val it : string option = Some "video/avi"

References: