Giter VIP home page Giter VIP logo

galaxus.functional's People

Contributors

adrianwaeber avatar alminsch avatar b4n4n4j03 avatar boskicthebrain avatar flipbug avatar freeapophis avatar nightruby-isa avatar noelwidmer avatar phkiener avatar raphaelimahorn avatar syrotkin 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

galaxus.functional's Issues

Add async Option.MapOr and Or

Would love to have async support for MapOr and Or on Option.

For async Pipelines sadly an unnecessary MapOr is needed if the fallback is async:
await option.MapOr(v => Task.FromResult(v), fallback)

Implementation of FirstOrNone, LastOrNone and SingleOrNone are not Lazy.

You do a ToList() in each of them, and lose the Lazyness of the Linq extensions which results in unwanted materialization of the whole IEnumerable<T>

FirstOrNone should only iterate to the first element, instead it materializes the whole list potentially thousands of elements. The same happens obviously in SingleOrNone, while it less of a problem in LastOrNone it is still not functional.

Helper methods and method helpers

Right now, the package is mostly focused on Option, Result and Either. It'd be nice to include some miscellaneous functions to ease working with lambdas everywhere...

  • Func<T2, T1, T3> Flip<T1, T2, T3>(Func<T1, T2, T3>)
  • Func<T, Unit> Do<T>(Action<T>)
  • T Identity(T)
  • Func<T> Const<T>(T)
  • Func<T1, T3> Compose<T1, T2, T3>(Func<T1, T2>, Func<T2, T3>)
  • Func<T2, T3> Bind<T1, T2, T3>(Func<T1, T2, T3>, T1)

And because of the beauty that is functional programming, the types should be enough to explain what the functions should do.

Option-Type value getter for dictionaries

Dictionary-like classes offer methods like bool TryGetValue<TKey, TValue>(TKey key, out TValue? value) or TValue? GetValueOrDefault<TKey, TValue>(TKey). To use dictionaries wie Galaxus.Functional it would be nice to have something like:

public static Option<TSome> GetValueOrNone<TKey, TSome>(this IReadOnlyDictionary<TKey, TSome> dictionary, TKey key)

Enforce (?) code style

Since putting "Oh, this formatting is wrong"-comments everywhere just isn't helpful, we should define a certain codestyle as standard and have a way to "enforce" it.

Either by adding an editorconfig (which is kind of a pain in the arse when supporting multiple IDEs/Editors) or StyleCop analyzers.. or whatever might exist outside of these two.

LINQ-Extensions using Option<T>

There are some LINQ methods like SingleOrDefault or FirstOrDefault which just return null if nothing matches. We should leverage the benefit of option to these extensions, providing SingleOrNone and similar extensions returning an Option<T>.

Add Result.FlatMap

Would love to have FlatMap option on Result.

Mapping with same error type packing them together.

In bigger Pipelines where the Result on a Map returns a Result itself makes it hard to chain together, especially if you are in an async context.

Result<Foo, Error> CreateFoo(Bar b);
Result<Bar, Error> CreateBar();

CreateBar().Map(b => CreateFoo(b)) // creates Result<Result<Foo, Error>, Error>

CreateBar().FlatMap(b => CreateFoo(b)) // Result<Foo, Error>

Add Option.MapOrElse

Would love to have support for MapOrElse on Option to simplify
option.Map(v => new Obj(v)).UnwrapOrElse(() => new Obj(fallback))

Add NUnit Testing Extensions

Create an additional Nuget that lets you write Tests like

Assert.That(result, Is.Result.InState.Ok.WithValue.GreaterThan(3))

or

Assert.That(option, Is.OptionOfSome.WithValue.EqualTo(2))

This new constraints should also have meaningfull messages if an Assert fails

Extract async-extensions into their own "module"

Right now, there's a lot of extensions for Result, Option and Either to handle async. MatchAsync, UnwrapAsync and all that.. and it kind of feels like noise in the midst of other extension that actually provide new functionality.

I think we could generate these extensions with a source generator, but I'd like to keep that distinctly apart from the rest of the library. So - I'd like to have all async functionaliry extrated to a different project Galaxus.Functional.Async.

It would still be contained in the same solution - and would still be packaged. The nuget package would simply contain both DLLs, with one being mostly generated code I guess.

Add a way to convert an Option<T> to an Either<A, T>

With Option<T>.ToEither(B) there is a way to convert an Option to an Either with a fallback value. The drawback is, that the Option's value will always be in the A spot and the fallback value in the B spot.

The order of the A, B, (and C) in an Either have no intrinsic semantic meaning. Therefore there exist legitimate cases, where you have an interface, requiring a parameter of type Either<X,Y> that you would like to call from an Option<Y> or an Either<Y,X>.

To achieve this, there are multiple solutions:

  1. Introduce a method e.g. Swap() on Either<TA, TB> returning an Either<TB, TA>
  2. Introduce two methods on an Option<X>: AsA(B valueIfNone) returning an Either<X, B> and AsB(A valueIfNone) returning an Either<A, X>

Polish package packing process

Right now, packing involves invoking dotnet pack with the correct path to the .nuspec files.

I'd love to:

  • Get rid of the .nuspec files, having all metadata inside the .csproj files
  • Having SourceLink set up for the packages
  • Making the build deterministic

In the end, I want the packing process to be as simple as doing dotnet pack -c Release -o packages/ in the repository root.

ConfigureAwait(false) for async extensions

Even though I'm not a huge fan of those, there's been a case now of Galaxus.Functional being used in code with a synchronization context. Lo and behold - Blazor.

To not be the cause of unneccessary slowdown, all the awaits should be accompanied by a ConfigureAwait(false).

Nullable reference types

The nullable reference types are a cool feature - the few places where do allow nulls would be a great place to put a shiny little ?.

Option to Either

It would be nice, if one could map an Option<TSome> to an Either<TSome, TNone> using a fallback of type TNone if the option contains None, without the need to specify the generic types explicitely or to use a Identity lambda function, since both are boilerplate.

I propose a new extension method like this:

public static Either<TSome, TNone> ToEither<TSome, TNone>(this Option<TSome> option, TNone fallback)
    => option.MapOr<Either<TSome, TNone>>(some => some, fallback);

Allow pattern-matching on Option, Result and maybe even Either

One of the cooler features in newer C# versions is pattern matching, especially something akin to

var foo = bar switch { <0: "Low", 0: "Zero", >0: "High" };

And one of the cooler features in Rust is being able to do this kind of pattern matching on Option and Result. So how cool'd it be to mimic this? Basically, being able to do the following:

var foo = bar switch { None: "Empty", Some x: $"Value is {x.Value}" };

Sadly, the compiler will probably warn about the patterns not being exhaustive since there's no catch-all, but maybe there's a way around that.

To do this, though, there'd need to be distinct types for the possibilities - basically imitating a discriminated union.

public abstract class Option<T>
{
  // Omitted
}

public sealed class Some<T> : Option<T>
{
  // Omitted
}

public sealed class None<T> : Option<T>
{
  // Omitted
}

The abstract base would then define all required operations (chaining, mapping, unwrapping) while the derived classes would just contain the very simple implementations, since there's no need to figure out if the current Option is a Some or a None.

This should easily be doable for Option and Result. For Either<A, B> and Either<A, B, C>, this would take some more effort.. maybe having a class A (please don't) implementing both Either<A, B> and Either<A, B, C> would be a possibility?

Consider an Option.Some constructor relying on type inference.

The type constructor of None currently is very verbose. You always have to give the type information of the inner type. This is not necessary in the some case, the type can be inferred from the value.

Instead of

var option = Option<TSource>.Some(value);

It should look like this:

var option = Option.Some(value);

Introduce Tap

When chaining Result's, there is often the need to work with the results value more than once, e.g. for logging and inform some listeners. One can use the functions Map and AndThen to do that, however, we than have to return the input again, which often requires to use heavier code, while with a Tap often a simple method group could be used.

With Tap one could write

result
    .Tap(Console.Write)
    .Tap(Publish);

Without the same functionality looks something like this:

result.
    .Map(ok =>
   {
        Console.Write(ok);
        return ok;
   }).Map(Publish);

The proposed naming is inspired by tap from rxjs and can be argued because of it's simmilarity to map.

As for Map and AndThen also a TapAsync as well as TapErr and TapErrAsync should be introduced.

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.