LanguageExt.Core

LanguageExt.Core Traits

A recent C# feature is static interface members – this opens up some new possibilities for bending C# to make trait like functionality work. You may have already seen the technique:

public interface Addable<SELF> where SELF : Addable<SELF>
{
    public static abstract SELF Add(SELF x, SELF y);
}

Note, how the Add member is static abstract and that the interface has a constraint that SELF is forced to inherit Addable<SELF>.

We can then create two distinct types that inherit the Addable trait:

public record MyList<A>(A[] values) : Addable<MyList<A>>
{
    public static MyList<A> Add(MyList<A> x, MyList<A> y) =>
        new (x.values.Append(y.values).ToArray());
}

public record MyString(string value) : Addable<MyString>
{
    public static MyString Add(MyString x, MyString y) =>
        new (x.value + y.value);
}

Language-Ext takes this idea and uses it to implement 'higher-kinded traits' (with the K<F, A> type being the anchor for them all).

To continue reading about how this works, check out Paul Louth's Higher-Kinds series.

Contents

Sub modules

Alternative
Applicative
Arithmetic
Bifunctor
Bool
Choice
Const
Domain
Eq
Fallible
Floating
Foldable
Fraction
Functor
Has
Hashable
Indexable
Liftable
Local
Monads
Monoid
MonoidK
Mutates
Num
Optional
Ord
Predicate
Range
Readable
Resolve
Resource
Semigroup
SemigroupK
Stateful
Traversable
UnliftIO
Writable

interface K <in F, A> Source #

Arrow kind: * -> * used to represent higher-kinded types.

K<F, A> should be thought of as F<A> (where both F an A are parametric). It currently can't be represented in C#, so this allows us to define higher-kinded types and pass them around. We can then build traits that expected a K where the trait is tied to the F.

For example:

K<F, A> where F : Functor<F>
K<M, A> where M : Monad<M>

That means we can write generic functions that work with monads, functors, etc.

Parameters

type F

Trait type

type A

Bound value type

interface K <in F, P, A> Source #

Arrow kind: * -> * -> * used to represent higher-kinded types.

Parameters

type F

Trait type

type P

Alternative value type

type A

Bound value type

class KExtensions Source #

Methods

method K<F, A> Kind <F, A> (this K<F, A> fa) Source #

Get the base kind type. Avoids casts mid-expression

method FA SafeCast <FA, F, A> (this K<F, A> fa) Source #

where FA : K<F, A>
where F : Functor<F>

method K<M, K<N, A>> KindT <M, N, NA, A> (this K<M, NA> mna) Source #

where NA : K<N, A>
where M : Functor<M>

KindT converts a nested Kind type (inherits K<M, A>), where the inner type is a concrete type and not K<N, A> to the more general version - which allows the other T variant methods to work seamlessly.

The casting of nested types is especially problematic for C#'s type-system, so even though this isn't ideal, it does allow for a truly generic system of working with any nested types as long as there's a Functor implementation for the outer type.

Parameters

type M

Outer functor trait (i.e. Seq)

type N

Inner trait (i.e. Option)

type NA

Concrete nested type (i.e. Option<int>)

type A

Concrete bound value type (i.e. int)

param mna

Nested functor value

returns

More general version of the type that can be used with other T extensions, like BindT

Examples

var mx = Seq<Option<int>>(Some(1), Some(2), Some(3));

var ma = mx.KindT<Seq, Option, Option<int>, int>()
           .BindT(a => Some(a + 1))
           .MapT(a => a + 1);
           .AsT<Seq, Option, Option<int>, int>();

method K<M, NA> AsT <M, N, NA, A> (this K<M, K<N, A>> mna) Source #

where NA : K<N, A>
where M : Functor<M>

AsT converts a nested Kind type (inherits K<M, A>), where the inner type is a general type (K<N, A>) to its downcast concrete version.

The casting of nested types is especially problematic for C#'s type-system, so even though this isn't ideal, it does allow for a truly generic system of working with any nested types as long as there's a Functor implementation for the outer type.

Parameters

type M

Outer functor trait (i.e. Seq)

type N

Inner trait (i.e. Option)

type NA

Concrete nested type (i.e. Option<int>)

type A

Concrete nested-monad bound value type (i.e. int)

param mna

Nested functor value

returns

Concrete version of the general type.

Examples

var mx = Seq<Option<int>>(Some(1), Some(2), Some(3));

var ma = mx.KindT<Seq, Option, Option<int>, int>()
           .BindT(a => Some(a + 1))
           .MapT(a => a + 1);
           .AsT<Seq, Option, Option<int>, int>();

interface Trait Source #

class TraitAttribute Source #

Fields

field string NameFormat Source #

Constructors

constructor TraitAttribute (string nameFormat) Source #