micro-elements - MicroElements.Functional 1.10.0

C# implementation of functional concepts: Maybe (Option), Either (Result), Try, Memoize

PM> Install-Package MicroElements.Functional -Version 1.10.0 -Source https://www.myget.org/F/micro-elements/api/v3/index.json

Copy to clipboard

> nuget.exe install MicroElements.Functional -Version 1.10.0 -Source https://www.myget.org/F/micro-elements/api/v3/index.json

Copy to clipboard

> dotnet add package MicroElements.Functional --version 1.10.0 --source https://www.myget.org/F/micro-elements/api/v3/index.json

Copy to clipboard
<PackageReference Include="MicroElements.Functional" Version="1.10.0" />
Copy to clipboard
source https://www.myget.org/F/micro-elements/api/v3/index.json

nuget MicroElements.Functional  ~> 1.10.0
Copy to clipboard

> choco install MicroElements.Functional --version 1.10.0 --source https://www.myget.org/F/micro-elements/api/v2

Copy to clipboard
Import-Module PowerShellGet
Register-PSRepository -Name "micro-elements" -SourceLocation "https://www.myget.org/F/micro-elements/api/v2"
Install-Module -Name "MicroElements.Functional" -RequiredVersion "1.10.0" -Repository "micro-elements" 
Copy to clipboard

MicroElements.Functional

Small subset of functional methodology in C#

Statuses

License NuGetVersion NuGetDownloads MyGetVersion

Travis AppVeyor Coverage Status

Gitter

Summary

MicroElements.Functional is another one try to use functional paradigm in C#. Functional approach can lead error elimination and more explicit logic.

Why I wrote one more lib? I tryed to use many monadic libs: louthy/language-ext, nlkl/Optional, la-yumba/functional-csharp-code, vkhorikov/CSharpFunctionalExtensions but there was some limitations or discomfort. LanguageExt is full featured but but it is very fat, Optional is very verbose and has only Option and Option with error, functional-csharp-code is cool but is a sort of book examples, all libs had not use new performance features of C#. And I decided to replace all functional libs with new... %)

Main features

  • Option
  • Result<A, Error> (Either)
  • Result<A, Error, Message>
  • ValueObject
  • Memoise
  • Try monad
  • Message and MessageList
  • Extensions for parsing, collections

Installation

Package Reference:

dotnet add package MicroElements.Functional

Build

Windows: Run build.ps1

Linux: Run build.sh

License

This project is licensed under the MIT license. See the LICENSE file for more info.

Usage

Option is value that can be in one of two states: Some(a) or None.

Creating Optional values

// Create some option.
var someInt = Some(123);

// Implicit convert to option.
Option<string> name = "Bill";

// None.
Option<string> noneString = None;
Option<int> noneInt = None;

// Extension method to create some value.
var someString = "Sample".ToSome();

Match

// Match returns (123+1).
int plusOne = someInt.Match(i => i + 1, () => 0);
Console.WriteLine($"plusOne: {plusOne}");

// Match returns 0.
int nonePlusOne = noneInt.Match(i => i + 1, () => 0);
Console.WriteLine($"nonePlusOne: {nonePlusOne}");

ValueObject

ValueObject is concept from DDD. see: https://martinfowler.com/bliki/ValueObject.html You need two main principle to implement ValueObject: Structural Equality and Immutability.

To implement ValueObject you need:

  • implement Object.Equals
  • implement Object.GetHashCode
  • implement Equality operator
  • implement Inequality operator
  • implement IEquatable interface (optional)
  • implement IComparable interface (optional)

Or you can just inherit your class from MicroElements.Functional.ValueObject and override GetEqualityComponents method.

MicroElements.Functional.ValueObject implements all routine for you. see Example.

Example

    /// <summary>
    /// Address for delivery.
    /// </summary>
    [ImmutableObject(true)]
    public class Address : ValueObject
    {
        public string Country { get; }
        public string City { get; }
        public string State { get; }
        public string ZipCode { get; }

        public string StreetLine1 { get; }
        public string StreetLine2 { get; }

        public string FullName { get; }
        public string PhoneNumber { get; }

        public Address(string country, string city, string state, string zipCode, string streetLine1, string streetLine2, string fullName, string phoneNumber)
        {
            //TODO: Domain checks
            Country = country;
            City = city;
            State = state;
            ZipCode = zipCode;
            StreetLine1 = streetLine1;
            StreetLine2 = streetLine2;
            FullName = fullName;
            PhoneNumber = phoneNumber;
        }

        /// <inheritdoc />
        public override IEnumerable<object> GetEqualityComponents()
        {
            yield return Country;
            yield return City;
            yield return State;
            yield return ZipCode;
            yield return StreetLine1;
            yield return StreetLine2;
            yield return FullName;
            yield return PhoneNumber;
        }
    }

Option

TODO

Either

TODO

Result

TODO

Design Notes

  • Most of types are structs so they can not be null
  • Don't use monadic values for persistence because structs have default constructors and can be in uninitialized state
  • Don't use monadic values in other data structures
  • Main monad type is A, result type is B or Res

Monad checklist

  • Readonly struct
  • Internal constructors, all factory checks in prelude
  • Monadic methods: Match, Map, Bind(FlatMap), Filter
    • inputs should be not null
    • result types named Res
  • LINQ operations: AsEnumerable, Select(Map), Where(Filter), SelectMany
  • Equality methods
  • Implicit conversions
  • Intermonad conversions
  • Uninitialized checks or bottom state?
  • Check Monad laws
  • Async interoparability or async version

Monadic operations

- B Match(Func<A, B> map);
- Monad<B> Map(Func<A, B> map);
- Monad<B> Select(Func<A, B> select);
- Monad<B> Bind(Func<A, Monad<B>> bind)
- Monad<C> SelectMany<B, C>(
     Func<A, Monad<B>> bind,
     Func<A, B, C> project)

$# 1.10.0

  • StringFormatter.DefaultFormatValue supports collections, and some tuple types

1.9.0

  • Lazy TypeCache
  • Fixed NodaTime TypeCache creation error
  • Added GetValueOrDefault for Result<A,Error> with default value

1.8.0

  • TypeCache AliasForType index
  • Added NodaTime TypeCache without direct reference

1.7.0

  • GetValueOrThrow for Result accepts allowNullResult that allows Result to have hull value as Success
  • Added extension IsNumericType and IsNullableNumericType
  • Added ErrorExtensions.ToException and ErrorExtensions.Throw
  • Added ReflectionExtensions and TypeCache
  • FormatAsTuple can limit render be items count and text length, allows to render name value tuples and collections

1.6.0

  • TypeCheck became public
  • Added methods to TypeExtensions: CanAcceptNull, CanNotAcceptNull, IsAssignableTo

Full release notes can be found at: https://github.com/micro-elements/MicroElements.Functional.git/blob/master/CHANGELOG.md

  • .NETStandard 2.1
  • .NETStandard 2.1: 2.1.0.0

Owners

Alexey Petryashev

Authors

micro-elements

Project URL

https://github.com/micro-elements/MicroElements.Functional

License

MIT

Tags

monads functional Maybe Option Either Result Try Memoize MicroElements

Info

2692 total downloads
78 downloads for version 1.10.0
Download (118.53 KB)
Found on the current feed only

Package history

Version Size Last updated Downloads Mirrored?
1.10.0 118.53 KB Wed, 02 Dec 2020 18:18:32 GMT 78
1.9.0 118.46 KB Wed, 02 Dec 2020 12:10:57 GMT 76
1.8.0 117.88 KB Tue, 01 Dec 2020 22:39:12 GMT 72
1.7.0 116.42 KB Sun, 29 Nov 2020 16:22:49 GMT 68
1.6.0 100.18 KB Thu, 19 Nov 2020 13:49:59 GMT 85
1.5.0 99.58 KB Sun, 15 Nov 2020 20:36:50 GMT 73
1.4.0 98.57 KB Wed, 11 Nov 2020 12:25:04 GMT 67
1.3.0 95.3 KB Tue, 27 Oct 2020 08:06:30 GMT 66
1.2.0 89 KB Tue, 20 Oct 2020 10:57:43 GMT 69
1.1.0 88.72 KB Mon, 19 Oct 2020 19:39:49 GMT 81
1.0.0 88.43 KB Sun, 11 Oct 2020 14:41:56 GMT 70
1.0.0-beta.4 88.46 KB Sun, 11 Oct 2020 14:41:48 GMT 66
1.0.0-beta.3 84.33 KB Fri, 17 Jul 2020 12:19:26 GMT 64
1.0.0-beta.2 84.28 KB Mon, 06 Jul 2020 14:28:22 GMT 82
1.0.0-beta.1 84.22 KB Mon, 06 Jul 2020 13:39:36 GMT 66
0.17.0 85.03 KB Tue, 05 May 2020 18:45:06 GMT 78
0.16.0 84.92 KB Mon, 24 Feb 2020 17:33:21 GMT 76
0.16.0-rc.4 75.57 KB Tue, 18 Feb 2020 16:13:09 GMT 76
0.16.0-rc.3 75.51 KB Tue, 18 Feb 2020 08:29:39 GMT 69
0.16.0-rc.2 75.45 KB Thu, 13 Feb 2020 19:54:06 GMT 83
0.16.0-rc.1 75.5 KB Sat, 19 Oct 2019 12:54:02 GMT 65
0.15.0 65.86 KB Tue, 30 Apr 2019 14:15:20 GMT 68
0.14.0 65.67 KB Tue, 23 Apr 2019 20:53:56 GMT 80
0.13.1 64.57 KB Sun, 14 Apr 2019 20:49:16 GMT 74
0.13.0 64.56 KB Tue, 09 Apr 2019 13:27:03 GMT 64
0.12.0 63.31 KB Thu, 14 Mar 2019 15:58:06 GMT 77
0.11.0 62.19 KB Wed, 13 Mar 2019 13:48:49 GMT 80
0.10.0 57.56 KB Fri, 01 Mar 2019 20:48:26 GMT 71
0.9.0 57 KB Wed, 27 Feb 2019 13:35:13 GMT 74
0.8.0 55.96 KB Sat, 23 Feb 2019 21:20:16 GMT 71
0.7.0 50.6 KB Tue, 12 Feb 2019 21:35:43 GMT 75
0.6.0 47.82 KB Sun, 10 Feb 2019 20:53:48 GMT 77
0.5.0 41.36 KB Sun, 03 Feb 2019 22:31:15 GMT 70
0.4.0 31.94 KB Sun, 27 Jan 2019 20:55:59 GMT 63
0.3.0 27.47 KB Wed, 23 Jan 2019 21:59:04 GMT 67
0.2.0 18.81 KB Tue, 15 Jan 2019 21:31:54 GMT 74
0.1.0 18.72 KB Tue, 15 Jan 2019 20:39:36 GMT 77