functional programming in c# and f#

52
#dotNETSpain2015 Alfonso García-Caro @alfonsogcn github.com/alfonsogarciacaro/dotNetSpain2015 Functional Programming in C# and F# .NET Conference 2015 Y A X B

Upload: alfonso-garcia-caro

Post on 14-Jul-2015

1.554 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Functional Programming in C# and F#

#dotNETSpain2015

Alfonso Garcí[email protected]/alfonsogarciacaro/dotNetSpain2015

Functional Programmingin C# and F#

.NET Conference 2015

Y

AX B

Page 2: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

Software Engineer at Green Eagle Solutions.Net and Web developerCollaborator of FunScript projectOrganizer of Madrid .Net and F# Meetups

About me

Page 3: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

Personal view of functional programmingEvery language and every programmer understands functional programming a bit differently. There will also be some simplifications.

Bias towards F# but I also love C#The sentence that will repeat most in this talk:“possible in C#, idiomatic in F#”

Not an utilitarian-only approachLike: “Immutability is good because makes parallelism easier”

...but won't bore you with tough MathsIf only because I wouldn't be able to.

Disclaimer

Page 4: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

Juan Pedro Villa Isaza, Category Theory applied to Functional Programming

[…] we are considering the objects and morphisms of Set to be the sets of all sets and all functions, respectively, which would lead to a paradox such as the set of all sets not members of themselves. For this reason, we ought to assume, for instance, that there is a big enough set, the universe, and take the objects of Set to be the sets which are members of the universe, that is, small sets. However, we shall not go into detail about mathematical foundations of category theory(*).

(*) Thank goodness!

Can functional really help me?

Page 5: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

My boss, at the office

Download real-time market price data from the internet at periodical intervals, insert it into the database and throw an event if the next hour price is lower than the threshold. In that case, communicate with the SCADA system through the OPC protocol to stop the wind turbines and check if the response has been successful.

Is there really anyway the former can help me with the latter?

Can functional really help me?

Page 6: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

We all use Math to write performant codeYes, those algorithms you copy from StackOverflow are Math ;)

Functional uses Math to organize your codeOr as others like to say, to reason about your code.

Two main topics...

Alonzo Church's Lambda CalculusCategory Theory

What is functional programming?

Page 7: Functional Programming in C# and F#

#dotNETSpain2015

Lambda CalculusIt's the composability, ***

Page 8: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

Turing revisitedOnly three rules to express all possible computations

(e stands for expression)Examples of lambdas:

e ::= x Reference Func<int, int> f = x => x + x; // C#

| λx.e Definition let f x = x + x // F#

| e e Application let f' = fun x -> x + x // F#

Wait, there is reference but no assignment?In strict functional there's no assignment, only binding.Binding is the same as definition an application at once.There's no re-binding either, and thus mutability is an alien concept.

Alonzo Church's Lambda Calculus

Page 9: Functional Programming in C# and F#

Bindingint add5(int x) { var five = 5; // Assigning a variable in local scope return x + five; // and performing a computation with it...}

int add5_(int x) { Func<int, int> f = five => x + five; // ...is the same as defining a function return f(5); // and applying it}

int add5__(int x) { var five = 5; // Look again: this is the parameter return x + five; // and this is the body of the function}

let add5 x = let five = 5 // Now in F# x + five // These three blocks are identical

let add5' x = (fun five -> x + five)(5) // Definition and application

let add5'' x = let five = 5 in // With the verbose syntax, you can see x + five // the body of the binding more easily

let add5''' x = let five = 5 // Error: binding body missing (in local scope)

Page 10: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

Q. Is this not a limitation to the expressiveness of the language?

A. Maybe, but if you look around you'll see that this design pattern is very common in nature.

Fractal theory

Complex design emerge from simple patterns.

Every element has very few dependencies.

Same structure at all levels: expression < function < module/file < library

Why few rules is a good thing?

Page 11: Functional Programming in C# and F#

Fractals in nature

Page 12: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

Lambda Calculus uses only expressionsDid you notice statements were also missing in Alonzo's rules?

Statements are like void functionsThey don't return a value, thus they only can have an influence in your program through side-effects.

Statements are everywhereVariable declarationConditionals: if/else, switchLoops: for, do, whileException: try/catchScope: usingVoid functions: I/O, state

Expressions vs Statements

Page 13: Functional Programming in C# and F#

Program flow

This is how the program flow looks with staments.

Notice there's no return arrow.

“Well, it doesn't look so bad”

Really?

Let's see it with side-effects.

Page 14: Functional Programming in C# and F#

Program flow

Side-effects break encapsulation.

Diagrams cannot be accurately represented with statements.

Side-effects depend on mutable state for every minor action (loops).

Page 15: Functional Programming in C# and F#

Alternatives to statements

Conditionals → ?: operator

Switch → Pattern Matching

Loops → LINQ, recursion

Exceptions → Monads

Page 16: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

Natural flowFluent APIs (e.g. LINQ) use expressions to chain operations naturally.Code readability is improved (see next page: visual honesty).

BranchingTechniques like pattern matching allow natural branching of the code.The Abstract Syntax Tree (AST) builds naturally.Diagrams can be represented more accurately.

Pure functionsStrict functional only allows pure functions.Pure functions always return a value and don't have side-effects.They don't break the program flow.

Expression merits

Page 17: Functional Programming in C# and F#

Visual Honesty with Fluent APIs

Source: www.theburningmonk.com

Page 18: Functional Programming in C# and F#

Pattern MatchingThe feature that sacrificed itself so C# 6.0 could be released on time

Page 19: Functional Programming in C# and F#

Pattern Matching

Switch on steroids

Page 20: Functional Programming in C# and F#

Pattern Matching// With some effort you can still get switch expressions in C#enum Pet { Dog, Cat, Bird }

static class Extensions { public static T Switch<T>(this Pet pet, Func<T> dog, Func<T> cat, Func<T> bird) { switch (pet) { case Pet.Dog: return dog(); case Pet.Cat: return cat(); case Pet.Bird: return bird(); default: throw new Exception("Inexhaustive matching"); } }}

class Program { public int HowOldIsMyPet(int animalYears, Pet pet) { return pet.Switch( dog: () => animalYears * DOG_YEARS, cat: () => animalYears * CAT_YEARS, bird:() => animalYears * BIRD_YEARS ); }}

Page 21: Functional Programming in C# and F#

Pattern Matching // Or even Union Types (aka Sum or Algebraic Types) public abstract class Option<T> { public readonly T Value; Option() { } Option(T value) { Value = value; }

public sealed class Some : Option<T> { public Some(T value) : base(value) { } } public sealed class None : Option<T> { public None() : base() { } }

public TOutput Match<TOutput>(Func<T, TOutput> some, Func<TOutput> none) { return this is Some ? some(Value) : none(); } }

class Program { public Option<string> foo() { return new Option<string>.Some("Foo!"); }

public string bar() { return foo().Match( some: name => "FOUND: " + name, none: () => "NOTHING"); } }

Page 22: Functional Programming in C# and F#

Pattern Matching// In F# these constructs are idiomatic and the syntax is much terser// Most of the times we use union types with Pattern Matching// Union types look like enum, but they can actually contain any value// We can extract this value when pattern matchingtype Pet = | Dog of int | Cat of int | Bird of int

let howOldIsMyPet pet years = match pet with | Dog dy -> years * dy | Cat cy -> years * cy | Bird by -> years * by

// Dummy methodslet riskyFn(): int option = failwith "Not implemented"let doSth(i: int): unit = failwith "Not implemented"

// Option type is a particular union type and it's built-inlet main() = match riskyFn() with | Some i -> doSth i | None -> ()

Page 23: Functional Programming in C# and F#

Syntax Trees are also in Nature

Page 24: Functional Programming in C# and F#

#dotNETSpain2015

Category TheoryRoad to Monads

Page 25: Functional Programming in C# and F#

Road to perdition?

Page 26: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

You're already using monadsLINQ and Task are also monads. Sort of.

If I already use them, do I need the theory?Think of it as the garbage collector, when you try to learn a bit about it, you can use it more efficiently.

But, what is category anyway?Is it not the same as a set?

Good news! (maybe)

Page 27: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

A collection with three componentsA collection of objectsA collection of morphismsComposition of the morphisms, which must be associative

How do they map to C#/F#?Objects are types (Attention!)Morphisms are functions

In F#, composition is the >> operator(f >> g)(x) = f(g(x))

In C#, composition is often represented with fluent APIsTask.Run(() => foo()) .ContinueWith(x => bar(x))

What is a category?

Page 28: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

CT provides us with a formal languageIf the program needs to be deterministic, we need a deterministic way to think about it.Obeying the laws it dictates can give us a proof of correctness.More practically, we can generate random tests to check whether the expected properties of our types are being fulfilled (FSCheck).

CT teaches us about transformationsIf our types and functions (categories) follow certain laws, we know we can apply some specific transformations.This is great, because there are many categories following these rules which we are not usually aware of.We are going to consider these categories as contexts as in non-deterministic, sequential or asynchronous contexts.

What is Category Theory useful for?

Page 29: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

Functors map one category into anotherIt could be represented as an interface like this (pseudo code):

F<a> Map<F,a,b>(this F<a> input, Func<a,b> f) // C#map: ('a → 'b) → 'F<'a> → 'F<'b> // F#

The Functor must follow these rules:F(id a) = id(F a) // identityF(f >> g) = F(f) >> F(g) // composition

Attention! The language doesn't enforce these rules, we must check them ourselves... but this is usually a work for library writers :)

The .NET type system doesn't allow this signature. However many contexts (say, generic types) implement it. Do you recognize it?

Our first transformation: the Functor

Page 30: Functional Programming in C# and F#

Functors in C# and F#public static Task<TOutput> Select<T, TOutput>(this Task<T> input, Func<T, TOutput> f) { return input.ContinueWith(t => f(t.Result));}

public static Nullable<TOutput> Select<T, TOutput>(this Nullable<T> input, Func<T, TOutput> f) where TOutput : struct { return input.HasValue ? new Nullable<TOutput>(f(input.Value)) : new Nullable<TOutput>();}

myList.Select(x => x + x); // Sequential contextmyTask.Select(x => x + x); // Asynchronous contextmyNullable.Select(x => x + x); // Non-deterministic context

// In F#, most contexts implement the map function// Instead of extension methods we often use module-bound functionstype Async<'a> with static member map f x = async { let! y = x in return f y }

let myList = [1; 2; 3;]let myOption: Option<int> = None // Option is preferred over Nullablelet myAsync: Async<int> = async { return 1 } // Async is prererred over Task

List.map (fun x -> x + x) myList // Functions can be chained with |> or >>Option.map (fun x -> x + x) myOption // myList |> List.map f |> List.map f'Async.map (fun x -> x + x) myAsync // List.map (f >> g) myList

Page 31: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

Abstraction is one pillar of functionalEverybody wants to program in a synchronous, deterministic context.

We don't need to worry about the implementation details of translating our computation to the context, the library does it for us.

This is may be trivial in certain contexts (IEnumerable, Nullable) but not in others (concurrent and parallel programming). The garbage collector for example has been abstracting the context of heap memory for years.

Abstraction favors composabilityWe can apply the same functions to different context or, at least, the same programming style.

Why abstract the context?

Page 32: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

What if we want to combine several contexts?With map we can only apply a computation to a specific context.

Sometimes we need to apply a function to several contexts at once. For example if we need to check all nullable fields of a UI form.

Then we need to move one step further and see Applicative Functors.

But before that we need to tackle another topic...

Partial applications

When mapping is not enough

Page 33: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

Pure functions only take one argumentFor example, when we see a function like this in F#:let f x y = x + y(We can also pass tuples, but let's focus on partial application no.)

It would translate to C# like:Func<int, Func<int, int>> f = x => y => x + y;

This way, if we apply only one argument we get a partially applied function:var add5 = f(5); // add5 == x => x + 5;

Why would we need that?Composability, remember?Anyway, with this knowledge we can keep on.

Partial applications

Page 34: Functional Programming in C# and F#

Applicative Functors in C#

// First lift the curried function to the domain of the contextpublic static IEnumerable<a> Pure<a>(a input) { return new a[] { input };}

// Then apply the function to the first operand. As the result is a partially applied// function, we can still apply it to the rest of the operandspublic static IEnumerable<b> Apply<a, b>(IEnumerable<Func<a, b>> liftedFn, IEnumerable<a> input) { foreach (var f in liftedFn) foreach (var x in input) yield return f(x);}

// TestFunc<int, Func<int, int>> add = x => y => x + y;var lifted1 = Pure(add);var lifted2 = Apply(lifted1, new int[] { 1, 2 } );Apply(lifted2, new int[] { 3, 4 }); // Output: 4, 5, 5, 6

Page 35: Functional Programming in C# and F#

Applicative Functors in C# public static partial class Option { public static Option<a> Pure<a>(a input) { return new Option<a>.Some(input); }

public static Option<b> Apply<a, b>(Option<Func<a, b>> liftedFn, Option<a> input) { return liftedFn.Match( some: f => Option.Map(input, f), none: () => new Option<b>.None() ); } }

public static partial class Async { public static Task<a> Pure<a>(a input) { return Task.Run(() => input); }

/// <summary>Caution: Simplified code, no error nor cancellation checks</summary> public static Task<b> Apply<a, b>(Task<Func<a, b>> liftedFn, Task<a> input) { var tcs = new TaskCompletionSource<b>(); liftedFn.ContinueWith(f => input.ContinueWith(x => tcs.SetResult(f.Result(x.Result)) )); return tcs.Task; } }

Page 36: Functional Programming in C# and F#

Applicative Functors in C#// Downloading several web pages using the Applicative Functor var downloader = new WebPageDownloader();Func<string, Task<string>> fetch10 = url => downloader.FetchLinesAsync(url, 10);

Func<string, Func<string, Func<string, string>>> curry = x => y => z => x + y + z;

var res1 = awaitAsync.Apply( Async.Apply( Async.Apply( Async.Pure(curry), fetch10("http://microsoft.github.io")), fetch10("http://fsharp.org")), fetch10("http://funscript.info"));

// Obviously, the syntax is not very pretty.// We can simplify it by providing methods to lift// functions with a fixed number of arguments.// Like...

Page 37: Functional Programming in C# and F#

Applicative Functors in C#public static partial class Async { // We can take the chance to add some optimizations (like parallelism) // But let's keep it simple for now public static Task<e> Lift3<a, b, c, e>(Func<a, b, c, e> f, Task<a> x, Task<b> y, Task<c> z){ Func<a, Func<b, Func<c, e>>> curry =

_x => _y => _z => f(_x, _y, _z);

var lifted1 = Pure(curry); var lifted2 = Apply(lifted1, x); var lifted3 = Apply(lifted2, y); return Apply(lifted3, z); }}

// Now the previous code can be rewritten as:await Async.Lift3( (x,y,z) => x+y+z, fetch10("http://microsoft.github.io"), fetch10("http://fsharp.org"), fetch10("http://funscript.info"));

Page 38: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

Source: http://www.slideshare.net/ScottWlaschin/

Lifting is not only for Hollywood stars

Page 39: Functional Programming in C# and F#

Applicative Functors in F#// In F#, thanks to type inference and other features the syntax is much terser// Also, many of the functions we need are already implemented// We can define our custom operators for an even lighter syntax toomodule Seq = let ``pure`` f = seq { yield f } // pure is a keyword in F#

let (<*>) f a = // <*> is often used for applying seq { for f in f do for a in a do yield f a } let (<!>) f a = ``pure`` f <*> a // Convenience operator

let f x y = x + y // Quick tests printfn "%A" (f <!> [3;4] <*> [2;1]) printfn "%A" (f <!> [3;4] <*> [])

module Option = let (<*>) f a = match f with | Some f -> Option.map f a | None -> None

let ``pure`` f = Some f let (<!>) f a = ``pure`` f <*> a

printfn "%A" ((+) <!> Some 5 <*> Some 4) // Quick tests printfn "%A" ((+) <!> Some 5 <*> None )

Page 40: Functional Programming in C# and F#

Applicative Functors in F#module Async = let ``pure`` f = async { return f } let (<*>) f a = async { let! f = f let! a = a return f a } let (<!>) f a = ``pure`` f <*> a

// Downloading content from the internet let fetchLines (url: string) i = async { let rec append i (s: StreamReader) (b: StringBuilder) = match i with | 0 -> b.ToString() | _ -> s.ReadLine() |> b.AppendLine |> append (i-1) s let req = WebRequest.Create(url) use! resp = req.AsyncGetResponse() use stream = resp.GetResponseStream() use reader = new StreamReader(stream) return append i reader (StringBuilder()) }

(fun x y z -> String.length x + String.length y + String.length z) <!> fetchLines "http://microsoft.github.io" 10 <*> fetchLines "http://fsharp.org" 10 <*> fetchLines "http://funscript.info" 10 |> Async.RunSynchronously |> printfn "Chars fetched: %i"

Page 41: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

What's a monad anyway?A monad is a monoid in the category of endofunctors, what's the problem? http://james-iry.blogspot.com.es/2009/05/brief-incomplete-and-mostly-wrong.html

What's a monad useful for?We've just seen how to lift a function so it can be applied to operands “wrapped” in a context. However, there are many cases when we want to unwrap an operand and return a result already in the context. Think of:

Sequential → Extract an element from a collection and return a collection (LINQ SelectMany())Non-deterministic → Extract the value of Nullable, Option, Either and return the result of a risky operationAsync → Extract the result of an asynchronous operation and perform another asynchronous operation

Monad is coming

Page 42: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

So we need a transformation with the following signature:

M<a> Return<a>(a input) // Same as Pure in ApplicativesM<b> Bind<a,b>(M<a> input, Func<a,M<b>> f)

return: 'a → 'M<'a>bind: 'a → ('M<'a> → 'M<'b>) → 'M<'b>

The return function is used to “leave the monad.”As monadic expressions are just abstract computations that we need later to apply into a context, the return value must be wrapped in the context.Thus, we have to “wrap” the result before leaving the monad.

(Depending on how the language implements the concept of monad, we may need to implement other functions. But let's ignore them for now.)

Mapping vs Binding

Page 43: Functional Programming in C# and F#

Monads in C#public static partial class Seq { public static IEnumerable<a> Return<a>(a input) { return Pure(input); } public static IEnumerable<b> Bind<a, b>(IEnumerable<a> input, Func<a, IEnumerable<b>> f) { return input.SelectMany<a, b>(f); }}

public static partial class Option { public static Option<a> Return<a>(a input) { return Pure(input); } public static Option<b> Bind<a, b>(Option<a> input, Func<a, Option<b>> f) { return input.Match( some: v => f(v), none: () => new Option<b>.None() ); }}

public static partial class Async { public static Task<a> Return<a>(a input) { return Pure(input); } /// <summary>Caution: Simplified code, no error nor cancellation checks</summary> public static Task<b> Bind<a, b>(Task<a> input, Func<a, Task<b>> f) { var tcs = new TaskCompletionSource<b>(); input.ContinueWith(x => f(x.Result).ContinueWith(y => tcs.SetResult(y.Result))); return tcs.Task; }

Page 44: Functional Programming in C# and F#

Monads in F#module Seq = let ``return`` f = seq { yield f }

let (>>=) xs f = // This is the usual operator for bind seq { for x in xs do yield! f x }

module Option = let ``return`` f = Some f

// Already implemented in FShap.Core let (>>=) a f = match a with | Some a -> f a | None -> None

module Async = // Already implemented in FShap.Core let ``return`` = async.Return let (>>=) a f = async.Bind(a, f)

Page 45: Functional Programming in C# and F#

And this is how we use themvar downloader = new WebPageDownloader(); // C#Func<string, Task<string>> fetch10 = url => downloader.FetchLinesAsync(url, 10);

var res1 = await Async.Bind( fetch10("http://microsoft.github.io"), x => Async.Bind( fetch10("http://fsharp.org"), y => Async.Bind( fetch10("http://funscript.info"), z => Async.Return(x + y + z) ) ));

let fetchLines (url: string) i = async { // F# let rec append i (s: StreamReader) (b: StringBuilder) = match i with | 0 -> b.ToString() | _ -> s.ReadLine() |> b.AppendLine |> append (i-1) s let req = WebRequest.Create(url) use! resp = req.AsyncGetResponse() use stream = resp.GetResponseStream() use reader = new StreamReader(stream) return append i reader (StringBuilder())}async.Bind(fetchLines "http://microsoft.github.io" 10, fun x -> async.Bind(fetchLines "http://fsharp.org" 10, fun y -> async.Bind(fetchLines "http://funscript.info" 10, fun z -> async.Return(x + y + z))))|> Async.RunSynchronously

Page 46: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

Is this any advance at all?Monads can be really useful, but nesting function is not pretty and soon leads to “callback hell.”

That's why most languages implementing monads add a macro system (sugar syntax) in order to make them more pleasant.

In C# we can use extension methods or even abuse the LINQ special syntax.

In F# we have computation expressions, designed for monads but including also many extra features:

Generators seq { for x in xs do yield x + x }Query expressions query { from x in db do select x }Macros for .NET constructs use!

But this is horrible!

Page 47: Functional Programming in C# and F#

Monads revisited// Extension method to use LINQ syntax with Taskpublic static Task<b> Select<a, b>(this Task<a> input, Func<a, b> f) { return Async.Map(input, f);}

public static Task<c> SelectMany<a,b,c>( this Task<a> input, Func<a, Task<b>> f, Func<a, b, c> projection) {

return Bind(input, outer => Bind(f(outer), inner => Return(projection(outer, inner))));}

// Now we can concatenate async operations using LINQ syntaxawait (from x in fetch10("http://microsoft.github.io") from y in fetch10("http://fsharp.org") let url = "http://funscript.info" from z in fetch10(url) select x + y + z);

// In F# the boiler plate code has already been done for us in Async// But we can implement our own custom computation expressions easilyasync { let! x = fetchLines "http://microsoft.github.io" 10 let! y = fetchLines "http://fsharp.org" 10 let url = "http://funscript.info" let! z = fetchLines url 10 return x + y + z }|> Async.RunSynchronously

Page 48: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

Why monads seems to be some pervasive in functional programming?Why I don't hear to talk about functors or applicatives so much?

Monads are an elegant idea. Same as map/reduce they can be used to deal in a similar fashion with many different problems.

In strict functional programming they have been used to tackle side-effects, for example: IO, State monads

We can also use the F# Async monad to code state machines without flags.

Feel the monad!

OK, I get the idea but...

Page 49: Functional Programming in C# and F#

State machines without state?

The state is in the program flow

Page 50: Functional Programming in C# and F#

#dotNETSpain2015

Now you're ready to join the functional army!

Page 51: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

Page 52: Functional Programming in C# and F#

#dotNETSpain2015#dotNETSpain2015

http://ericlippert.com/2013/02/21/monads-part-one/Monads and C#, by Eric Lippert

Real-World Functional Programming, with examples in F# and C#By Tomas Petricek and Jon Skeet

http://fsharpforfunandprofit.com/By Scott WlaschinThe site to learn F# and functional programming, from an F# perspective

http://learnyouahaskell.com/By Miran LipovacaA strict functional language helps you understand better the concepts

http://bugsquash.blogspot.com.es/By Mauricio Scheffer

References