New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Samples #209

Closed
Skoucail opened this Issue Apr 21, 2017 · 5 comments

Comments

Projects
None yet
4 participants
@Skoucail

Skoucail commented Apr 21, 2017

Can i find some Samples/Tutorials somewhere?
I'm a typical c# programmer who would like to use some more functional principles to clean up my code.
I already checked out the Pluralsight course on functional programming in c# and trough some googling came to this lib.

Now a sort of "Getting started with language-ext" would be nice. As now i find it pretty hard to just take a small program/piece of code and just refactor it. Maybe some before and after examples would be very helpful for people tying to get into using language-ext.

@louthy

This comment has been minimized.

Owner

louthy commented Apr 21, 2017

@Skoucail You may want to start with a book, I can recommend Functional Programming in C#; I've been a technical proofer on that book and would recommend it highly. There's a lot of cross-over to what I have built here.

The key thing with functional programming in C# is being strict with yourself, as it's easy to fall into the OO habits. Primarily it's about:

  • Expression oriented programming - making everything you do an expression, rather than a sequence of statements (you can always tell if you've got an expression because the first thing in a method is return, or you're using the expression-bodied methods that don't have braces and start with =>)
  • Get the OO notion of functionality and data being attached out of your mind. Create immutable types (see my StackOverflow answer here for info); they act like 'record types' or 'data types' in other functional languages. And then create static classes that work with the data-types.
  • Write pure methods. Pure methods are referentially transparent. They don't refer to any global state, and work solely with the values provided to the method. Combined with immutable types it allows you to consider the result of a pure method to be exactly like a value, because every time you provide the same inputs you get the same output.
  • Try to avoid throwing exceptions. Exceptions are like a goto, and do not fit the expression oriented mentality. Instead return Option<A> to indicate success or failure, or Either<L, R> where L is the error value and R is the success value.
  • For the occasions where you're using code that might throw an exception, use Try<A>. It will catch the exception and allow you to match or map on the result.
  • Learn what functors, applicatives, and monads are. They're scary terms, but so is 'polymorphism' when you first start OO. Functors are types with a Map function (also known as Select in LINQ). They allow you to 'stay in context' with some of the core functional types like Option<A>, Either<L, R>, Try<A>, etc.

For example, let's say you have a function that can return an optional result (so instead of throwing an error, you return None):

    Option<string> GetValue(bool hasValue) =>
        hasValue
            ? Some("Skoucail")
            : None;

Option<A> doesn't allow you to get at the inner value of the type without matching:

    string value = GetValue(true).Match(
        Some: name => $"Hello, {name}",
        None: () => "Goodbye"
    );

Now doing that all the time you want to work with optional values is pretty annoying. And this is where functors and monads come in. So with functors you can stay in the optional context by mapping:

    Option<string> value = GetValue(true).Map(name => $"Hello, {name}");

So instead of jumping back out to the string, you stay in the Option<string> context. You can maintain this for as long as necessary by doing subsequent calls to Map. The key thing is that the lambda inside the Map won't be invoked if the Option is in a None state. So Option is a replacement for if statements, and reduces the cyclomatic complexity of your code.

Monads are classically a difficult subject for people coming at OO. But don't worry too much about their name, just know that most of the types in language-ext are monads. Monads have two requirements:

  1. To have a constructor function
  2. To have a bind function

The constructor function just makes a new monad of whatever type. The Some(x) and None functions above construct the Option monad. Usually in functional programming it's called Return which adds to the confusion, but don't worry about that for now.

The Bind function is almost exactly the same as the Map function. Except where Map takes a Func<A, B> to map an A to a B; Bind takes a Func<A, M<B>>, where M is the monad type. So for Option its Func<A, Option<B>>. So in other words you're mapping an A to a monad of B. This allows you to chain multiple functions together that all return Option for example:

    Option<string> GetFirstName() => 
        Some("Joe");

    Option<string> MakeFullName(string firstName) => 
        Some($"{firstName} Bloggs");

    Option<string> name = GetFirstName().Bind(MakeFullName);

So of course if either GetFirstName() or MakeFullName() returned None then name would be None.

Again that starts to get a bit unwieldy, but C# has syntax for monadic types: LINQ:

    Option<string> GetFirstName() => 
        Some("Joe");

    Option<string> GetLastName() => 
        Some("Bloggs");
    
    var name = from first in GetFirstName()
               from last in GetLastName()
               select $"{first} {last}";

Whenever you see a from x in y, you should always think that y is a monad, and that x is the value inside the monad. IEnumerable is a monad as well.

Why is this better? Well, it avoids you writing the same shit over and over:

    var name = "";
    var firstName = GetFirstName();
    if(firstName != null)
    {
        var lastName = GetLastName();
        if(lastName != null)
        {
            name = $"{first} {last}";
        }
    }

So Option removes the need to write if statements, so does Either but gives you an alternative value for when it fails (else). Try avoids the need to write try/catch statements. TryOption is a combination of returning an optional result and catches exceptions, etc.

The collection types in lang-ext are all immutable types, which are much more robust than mutable ones, and are easier to use when writing pure functions. Lst<A> is a List<A> replacement, Set<A> and HashSet<A> replace the BCL HashSet<A>, Map<A, B> andHashMap<A, B> replace SortedDictionary<A, B> and Dictionary<A, B>; Seq<A> is a better IEnumerable which doesn't suffer from multiple evaluation traps, etc.

Summing up

The best thing to do is start working with expressions more, start using Option more, get friendly with the ternary operator for conditional expressions (a ? "true" : "false" instead of if(a) ...); it will take time to all sink in, and may seem bat shit crazy at times, but take it from me as a reformed OO guy, that it will be worth it, and you'll wonder why you ever wrote OO in the first place. You'll have several 'aha' moments, but it can take a few years to really master it, although there's tons more resource around now compared to when I started it. Most of the functionality in this library are here to help you to compose expressions, that is the absolute key to all of this: to make your code act like a mathematical formula - which gives you super powers as a programmer when it comes to reasoning about it (and from stopping it code-rotting over time).

You may want to have a look at the unit tests for examples, although they're not particularly presented in a style that's useful for tutorials.

@jeremysmith1

This comment has been minimized.

jeremysmith1 commented Apr 21, 2017

I would like to second the functional c# programming book suggestion. I started reading it without any functional experience and felt very comfortable afterwards. The extensions the book uses is almost identical to this project.

@Skoucail

This comment has been minimized.

Skoucail commented Apr 21, 2017

Will take a look at the book for sure.
And thx for the short summary.
Maybe in a few years i will be able to call myself a reformed OO guy too!

@Skoucail Skoucail closed this Apr 21, 2017

@louthy

This comment has been minimized.

Owner

louthy commented Apr 21, 2017

@Skoucail Good luck! I guess one final point, and I know it's kinda obvious, but it's all about functions. Functions are the unit of currency, whether they're pure static functions or first class functions (Func<...>) that you pass around. Dependency Injection for example is terrible in OO land, yet in functional land it's just done with Func and is the core idea behind the paradigm. Even the high-abstraction stuff like monads, applicatives, and functors are all just about function composition.

@jeremysmith1 That's great to hear :)

@louthy louthy assigned louthy and unassigned louthy Jun 7, 2017

@manfredk

This comment has been minimized.

manfredk commented Oct 29, 2017

Again, praise to the book by Enrico Buonanno, which really is an eye-opener and by far the best book for ambitious C# developers trying to adopt functional principles. @louthy Kudos to you and all people working as proofers and editors on Enricos book - the released book shows substantial improvements in quality over the MEAP versions (which already were worth the money).

Regarding monads, there's this great article by Eric Lippert here, which really helped me to wrap my brains around the concept. On top of that Enrico does a great job in explaining the intricacies of functors and such.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment