Coder Social home page Coder Social logo

functional-csharp-code's Introduction

Functional Programming in C#

This repo contains the code samples, exercises and solutions for the book Functional Programming in C# published by Manning.

Functional Programming in C#

The code samples are organized in the following projects:

  • Examples: examples used throughout the book, by chapter
  • Exercises: placeholders for you to do the exercises, compile and run them; and compare to the provided solutions
  • LaYumba.Functional: a functional library that we develop throughout the book
  • LaYumba.Functional.Data: very simple functional data structures discussed in Chapter 9
  • LaYumba.Functional.Tests: also illustrative of topics explained in the book, and useful to better understand the constructs in the library
  • Boc.Domain: an example of using F# for domain objects

Note: you are welcome to reference LaYumba.Functional from your projects via NuGet, and submit PRs with improvements, but the main intent of this library is pedagogical. For a more fully-fledged functional library, consider LanguageExt

Working with the code samples

The code samples use .NET Standard 1.6 and .NET Core 2.0, and should compile and run on all major OS's via the dotnet CLI.

Prerequisites

To check this is available, type dotnet --version at the command prompt, and you should get 2.0.3 or greater

One-time setup

$ git clone [email protected]:la-yumba/functional-csharp-code.git
$ cd functional-csharp-code
$ dotnet restore

Running the tests

Use the dotnet test command, for example:

$ cd LaYumba.Functional.Tests
$ dotnet test

tests in the Exercises and Examples projects can be run in the same way.

Running examples

Many code samples in the book can be run, in case you'd like to debug or "see that it works". The pattern is:

$ cd Examples
$ dotnet run Greetings
Section Command
7.1 dotnet run Greetings

Setting up the REPL

Throughout the book, I encourage readers to try things out in the REPL.

  • If you use Visual Studio, you can start the REPL by going to View > Other Windows > C# Interactive (short tutorial here)
  • On Mono, use the csharp command
  • There are several other REPLs available, some even run in the browser

You'll often need to import LaYumba.Functional in the REPL. In C# Interactive, this can be done like so:

#r "functional-csharp-code\LaYumba.Functional\bin\Debug\netstandard1.6\LaYumba.Functional.dll"

The path above may not work for you, in which case use an absolute path to the dll, or type Directory.GetCurrentDirectory() into the REPL to see what to use as a base for a relative path.

Next, add these imports:

using LaYumba.Functional;
using static LaYumba.Functional.F;

You're now ready to experiment with functional code right in the REPL, for example:

> Func<int, int, int> plus = (a, b) => a + b;
> Some(plus).Apply(1).Apply(2)
[Some(3)]
> Some(plus).Apply(1).Apply(None)
[None]

Doing the exercises

  • edit the code in Exercises as needed

  • edit Exercises/Program.cs to start the class you want

  • run it with:

    $ cd Exercises
    $ dotnet run
    
  • run your tests:

    $ cd Exercises
    $ dotnet test
    

functional-csharp-code's People

Contributors

draptik avatar hpcsc avatar la-yumba avatar zhenyagusev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

functional-csharp-code's Issues

Can we create an Entity framework model using custom types?

Take the Age type from chapter 3 as an example (source code).

Suppose I want to create a Person class, that EF will map to a table...

  public class Person
  {
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public Age Age { get; set; }
  }

I don't want Age to be mapped to a table, but can't see a way of convincing EF Core about this.

Anyone any ideas? Can we even use custom types with EF Core?

Thanks

Currying up to 9 arguments

I enjoy using LaYumba for teaching.

Anybody interested in Currying up to 9 arguments?

Reason I'm asking: in a previous course (using LaYumba) it took me some time to figure out why the students code wasn't working: ...the student used Apply for a function with more than 3 arguments...;-)

Currently, currying only supports 3 arguments.

Would a pull request be of interest to other people?

Cannot Build the project

I'm getting this error when am trying to restore the project or build it using dotnet build, dotnet restore.
I'm using visual studio 2019 and .NET 6.
But I also added global.json file to restore and build the project using version 2.2.202 but still getting the same error.
Can you please advise.

C:\Program Files\dotnet\sdk\2.2.202\NuGet.targets(119,5): error : Unable to load the service index for source https://dotnet.myget.org/F/dotnet-core/api/v3/index.json. [E:\layumba_functional\functional-csharp-code\VS2017.sln]
C:\Program Files\dotnet\sdk\2.2.202\NuGet.targets(119,5): error : The SSL connection could not be established, see inner exception. [E:\layumba_functional\functional-csharp-code\VS2017.sln]
C:\Program Files\dotnet\sdk\2.2.202\NuGet.targets(119,5): error : The remote certificate is invalid according to the validation procedure. [E:\layumba_functional\functional-csharp-code\VS2017.sln]
0 Warning(s)
1 Error(s)

Thank you so much

Unpon fresh clone, the solution does not build

Problem

I just cloned the repository and tried to build.
VS 2019 gives me the following error:
image

Running dotnet restore then reveals the real issue (sorry - German)
image

The index for the source "https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" cannot be loaded - the SSL connection could not be established. It seems the remote certificate is invalid.

Solution

This can easily be fixed by running
dotnet restore --ignore-failed-sources

Thereafter the build succeeds.

You may still want to

  1. either fix this or (what do you need the myget repo for?)
  2. inform new users of this repo by providing a hint in the readme.md

What do you prefer?

Exceptional<T> bool checks Success and Exception and IEnumerableExt FirstOr not accessible in 2.0.0 nuget package

I have been using version 1.0.0 on .NET 5 in a project for improving my FP knowledge. I've moved to .NET 6 and upon trying to upgrade from the 1.0.0 to 2.0.0 LaYumba nuget package I receive code errors for Exceptional where if I were performing a check on the Exceptional with Exception or Success bool.

resp.Exception == true

These checks against Exception or Success are now causing build errors with 2.0.0. I looked into the definition for Exceptional in VS and 1.0.0 contains the following.

public bool Success => Ex == null;
public bool Exception => Ex != null;

2.0.0 refactored them to the following.

private bool IsSuccess
{
    get;
}

private bool IsException => !IsSuccess;

The master branch on Github contains the following.

public bool Success => Ex == null;
public bool Exception => Ex != null;

I also get the same for FirstOr from IEnumerableExt. 1.0.0 works, move to 2.0.0, can't find it, and master still contains a public generic method for it.

Did I miss a posting that these were to change? Are these permanent changes?

Ambiguous call to SelectMany

Here is a link to a gist reproducing the problem i'm running into

Ambiguous call to SelectMany

I'm guessing the compiler can't decide whether to use the SelectMany on Task vs the SelectMany on Task<Validation>.

I'm finding the current design doesn't allow us to implement the query pattern on our custom monad stacks. Currently, the query pattern overloads are automatically included with the import of LaYumb.Functional, so how do we pick which overload our stack should use?

Should maybe the extension methods that implement the linq query pattern be moved into their own namespace and require and explicit import statement?

Alternative, type-safe approach to Middleware<T>

Enrico, I'm a big fan of your book. So much, that I even dived deeper in the subject of Middleware you introduced in Chapter 11. One thing that I couldn't stop thinking about was the usage of dynamic in your definition. I was thinking about it over the last weekend and I think I created an interesting, alternative approach which is fully type-safe.

I described the whole story in my blog.
http://www.itisnotoverengineering.com/2018/10/idisposable-monad-iusable-part-1.html
http://www.itisnotoverengineering.com/2018/10/idisposable-monad-iusable-part-2.html

I would love to hear your opinion about it. Maybe you could even include it in the second edition of your book :)

Thanks,
Stan

How to lift a function into Validation

In book P198, I learned how to lift a function into Validation by calling Valid(PhoneNumber.Create).
But it didn't work in my exercise. Valid is only used for data type T, not a function. Can someone help me out? Thanks.

Example using Exceptional.Apply

Do you have a working example of using Exceptional.Apply?

I'm a little confused in the usage, I'm supposed to Lift first a fn to Exceptional and then apply the arguments

In the following snippet, the first line works and the second get an unmanaged exception. Not sure if apply should manage that in the same way Try.Run does, any thoughts?

   [Test]
    public void Test_Apply()
    {
        // Arrange
        Func<string, int> ParseString = text => int.Parse(text);
        var SafeParseString = Exceptional(ParseString);
        
        // Act
        var result = SafeParseString.Apply(Exceptional("1"));
        var result2 = SafeParseString.Apply(Exceptional("X"));
    }

public static field vs public property with get for Functions

In Chapter07's solution, you had Remainder defined as

public static Func<int, int, int> Remainder = (dividend, divisor)
     => dividend - ((dividend / divisor) * divisor);

why don't we have them as public property? what's the difference?

public static Func<Dividend, Divisor, int> Remainder
{
    get { return (dividend, divisor) => dividend - (dividend / divisor) * divisor; }
}

In expression body:

public static Func<int, int, int> Remainder => (dividend, divisor)
     => dividend - ((dividend / divisor) * divisor);

Error thrown for list of working employees

If we pass to AverageYearsWorkedAtTheCompany an empty list or a list that contains only employees that still employed, method Average() will throw an exception, as it requires at least one element (

static double AverageYearsWorkedAtTheCompany(List<Employee> employees)
).
I've solved it like this: https://github.com/emanuelefirmani/FunctionalProgrammingCSharp/blob/master/FunctorsMonads/WorkPermitCode.cs#L20

Using the Exceptional with function returning Task<List<T>>

Hello, I am trying to use the Exceptional class in a function which queries the database and returns a Task<List<T>>. I am having a hard time understanding how to catch DB exceptions and return Exceptional within this function.

Here is the function:

public static Task<List<T>> ExecuteStoredProcedureAsync<T>(this ConnectionString connectionString, Some<string> spName, Some<object> spParamObj)
        {
            using SqlConnection connection = new SqlConnection(connectionString);
            var list = connection.QueryAsync<T>(spName, spParamObj.Value, commandType: CommandType.StoredProcedure).Result ?? new List<T>();

            return Task.FromResult(list.ToList());
        }

I started to add exception handling with the Exception class, like so:

public static Task<Exceptional<List<T>>> ExecuteStoredProcedureAsync_TEST<T>(this ConnectionString connectionString, Some<string> spName, Some<object> spParamObj)
        {
            try
            {
                using SqlConnection connection = new SqlConnection(connectionString);
                var list = connection.QueryAsync<T>(spName, spParamObj.Value, commandType: CommandType.StoredProcedure).Result ?? new List<T>();

                return Task.FromResult(F.Exceptional<List<T>>(list.ToList()));

            }
            catch (Exception ex)
            {
                return ex;
            }
        }

But, this obviously cannot work as the return type in the exception block needs to be compatible with the function's return type. I was under the assumption that the Exceptional class will convert to the appropriate type, but this seems to not be the case.

Can anyone help point me in the right direction. Thank you for your time.

Match on Either<,> Needs to Return Type Over ValueTuple from Async Lambda

We are having issues with correct async usage and correct type returning from and async call within a Match on Either<,> that was returned. This isn't an issue with the LaYumba package and more of an issue of we don't know the fix and would like to try to get more FP experienced eyes on it to help solve it.

https://stackoverflow.com/questions/70655009/match-on-either-needs-to-return-type-over-valuetuple-from-async-lambda

Sorry if this is not where this should be posted, but only initial place I could think of.

Performance of the library

Hi!

It's basically a question, not an issue. And sorry for asking it here. I just didn't find any other propper place for asking, like author's site or forum, etc.
I'm reading the book. And I'm very much excited about it. Very eager to use the shown technics in my own code.
But I'm a bit worried about performance. Some niceties shown in the book (and hence availbale in the library) definitely comes for a cost of an overhead either in performance or memory consumption. I'm currently on the chapter 4, and I've found at least two such questionable cases.

  1. Struct Option. For the lack of some constructions (like a record) in C#, this type is implemented with some workarounds like wrapping given value to an instance of another struct, which in addition has an extra member of bool (overhead both in memory and in performance due to initialization code).

  2. ForEach pattern. In order to make it work with Actions, it converts Action to Func and creates an IEnumerable kind of implicitely for a client who uses the library. So when calling ForEach on an array of a million elements, it will additionally create yet another array of million elements... Well, most likely it will be short living array. But such an immediate burst in memory consumption can be still very sensitive.

Have any performance tests been run on the library which would compare performance impact of library to a similar 'traditional' code? I mean 'traditional' in a sense that it does the same but looks maybe uglier, 'dishonest', etc.

Thank you!

Code errors

In Chapter 10, the code is
`var startOfPeriod = new DateTime(year, month, 1);
var endOfPeriod = startOfPeriod.AddMonths(1);

     var eventsBeforePeriod = events
        .TakeWhile(e => e.Timestamp < startOfPeriod);
     var eventsDuringPeriod = events
        .SkipWhile(e => e.Timestamp < startOfPeriod)
        .TakeWhile(e => endOfPeriod < e.Timestamp);`

I think the correct code should be
var eventsDuringPeriod = events .SkipWhile(e => e.Timestamp < startOfPeriod) .TakeWhile(e => e.Timestamp < endOfPeriod );

Option.Map results in exception creating a new Some(null)

Hi.
First off: reading the book at the moment and think it's great. Thank you.

I encountered a bug today when I tried to do this:

return Option<T>.Map(t => t.NullableA?.NullableB) // and either nullable A or B were null!

Creating a Some with a value of null threw an exception.
My first thought was 'why doesn't that just create a None instead of throwing' but then I realised Its because its within a constructor.

What would you recommend as a sensible replacement to the code above?
I replaced it with

return Option<T>.Match( Some: t => t.NullableA?.NullableB is null ? None : Some(b.NullableA?.NullableB), None:() => None);

I'm assuming I've misunderstood something.
Thanks
Dave

.NET Core 2.0 support

Hi,

Is it possible to upgrade the project to support .NET Core 2.0? There are quite a lot of changes from 1.1 to 2.0, especially migration from project.json to msbuild. Most of people should use 2.0 now

And thanks for the awesome book. I really enjoy reading it

Name conflicts with String and Enum

When using this library, there is often the need to specify

using String = System.String;
using Enum = System.Enum;

because the library defines String and Enum, which conflict with the respective classes in System.

The two classes are meant to host some helper functions.

Maybe they can be renamed to avoid name conflicts?

Nuget Package Circular Reference in LinqPad

Hi,

Firstly - thank you for an incredible book! Without exaggerating, I've been wanting something like this for between five and ten years.

Not sure if it's an issue with your packages or LinqPad, but when I try to pull the nuget into the latter I get this issue.

image

Thanks again :-)

Need help with this code

Just reading your greate book and studing the code. Can you explain, why Unit is needed in below SelectMany function?

  public static async Task<RR> SelectMany<R, RR>
         (this Task task, Func<Unit, Task<R>> bind, Func<Unit, R, RR> project)
      {
         await task;
         R r = await bind(Unit());
         return project(Unit(), r);
      }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.