Migrate to `net461` and `netstandard2.1`
NOTE: I am just investigating some issues with this release relating to the code-gen, keep an eye out for 3.4.3 tonight or tomorrow (12/Feb/2020)
In an effort to slowly get language-ext to the point where .NET Core 3 can be fully supported (with all of the benefits of new C# functionality) I have taken some baby steps towards that world:
Updated the references for CodeGeneration.Roslyn
to 0.7.5-alpha
This might seem crazy, but the CodeGeneration.Roslyn
DLL doesn't end up in your final build (if you set it up correctly), and doesn't get used live even if you do. So, if the code generates correctly at build-time, it works. Therefore, including an alpha
is low risk.
I have been testing this with my TestBed and unit-tests and working with the CodeGeneration.Roslyn
team and the alpha
seems stable.
A release of CodeGeneration.Roslyn
is apparently imminent, so, if you're not happy with this, then please wait for subsequent releases of language-ext when I've upgraded to the full CodeGeneration.Roslyn
release. I just couldn't justify the code-gen holding back the development of the rest of language-ext any more.
Updated the minimum .NET Framework and .NET Standard versions
Ecosystem | Old | New |
---|---|---|
.NET Framework | net46 |
net461 |
.NET Standard | netstandard2.0 |
netstandard2.1 |
OptionAsync<A>
and EitherAsync<A>
support IAsyncEnumerable<A>
The netstandard2.1
release supports IAsyncEnumerable<A>
for OptionAsync<A>
and EitherAsync<A>
. This is the first baby-step towards leveraging some of the newer features of C# and .NET Core.
pipe
prelude function
Allow composition of single argument functions which are then applied to the initial argument.
var split = fun((string s) => s.Split(' '));
var reverse = fun((string[] words) => words.Rev().ToArray());
var join = fun((string[] words) => string.Join(" ", words));
var r = pipe("April is the cruellest month", split, reverse, join); //"month cruellest this is April"
Added Hashable<A>
and HashableAsync<A>
type-classes
Hashable<A>
and HashableAsync<A>
provide the methods GetHashCode(A x)
and GetHashCodeAsync(A x)
. There are lots of Hashable*<A>
class-instances that provide default implementations for common types.
Updates to the [Record]
and [Union]
code-gen
The GetHashCode()
code-gen now uses Hashable*<A>
for default field hashing. Previously this looked for Eq*<A>
where the *
was the type of the field to hash, now it looks for Hashable*<A>
.
By default Equals
, CompareTo
, and GetHashCode
use:
// * == the type-name of the field/property
default(Eq*).Equals(x, y);
default(Ord*).CompareTo(x, y);
default(Hashable*).GetHashCode(x);
To provide the default structural functionality for the fields/properties. Those can now be overridden with The Eq
, Ord
, and Hashable
attributes:
[Record]
public partial struct Person
{
[Eq(typeof(EqStringOrdinalIgnoreCase))]
[Ord(typeof(OrdStringOrdinalIgnoreCase))]
[Hashable(typeof(HashableStringOrdinalIgnoreCase))]
public readonly string Forename;
[Eq(typeof(EqStringOrdinalIgnoreCase))]
[Ord(typeof(OrdStringOrdinalIgnoreCase))]
[Hashable(typeof(HashableStringOrdinalIgnoreCase))]
public readonly string Surname;
}
The code above will generate a record where the fields Forename
and Surname
are all structurally part of the equality, ordering, and hashing. However, the case of the strings is ignored, so:
{ Forename: "Paul", Surname: "Louth" } == { Forename: "paul", Surname: "louth" }
NOTE: Generic arguments aren't allowed in attributes, so this technique is limited to concrete-types only. A future system for choosing the structural behaviour of generic fields/properties is yet to be designed/defined.