Skip to content

Releases: polyadic/funcky

Funcky 3.5.0 | Funcky.Async 1.4.0 | Funcky.Xunit 2.1.0 | Funcky.Analyzers 1.4.0

15 Jan 14:38
24289b5
Compare
Choose a tag to compare

This update is mainly to update to .NET 9 but also has several smaller improvements.

.NET 9

Thanks to the new [OverloadResolutionPriority] attribute, we've been able finally fix
the ambiguous call errors when using DictionaryExtensions.GetValueOrNone:

Dictionary<string, string> favouriteFoods = new();
Option<int> tausFavouriteFood = favouriteFoods.GetValueOrNone("Tau");
//                                             ^^^^^^^^^^^^^^
// This used to produce a `error CS0121: The call is ambiguous between ...` error
// and now simply works 🎉

In good old fashion, we've also added new parse extensions:

  • ParseExtensions.ParseAssemblyNameInfoOrNone
  • ParseExtensions.ParseTypeNameOrNone

Policy for EOL Target Frameworks

We've explicitly written down our policy for how we deal
with older / EOL target frameworks.

In short: EOL target frameworks are supported by Funcky until the next major version.
However, we may no longer test Funcky against those target frameworks, so we
can't guarantee that everything works smoothly.

New APIs

In Funcky 3.0 we've changed CycleRange and RepeatRange to return an IBuffer
to enable us to memoize the collection, preventing unnecessary enumeration. This however
is unpractical for uses where you want to cycle an already materialized collection.
This release adds two new methods to accommodate that use case:
CycleMaterialized and RepeatMaterialized.

For convenient downcasting of Option<T>, Result<T> and Either<TLeft, T> values, we've added a new
DownCast class:

Option<object> option = Option.Some("hello world");
Option<string> downcasted = DownCast<string>.From(option);

Funcky.XUnit

Funcky.XUnit has been updated to the latest version (2.9.3) of xUnit.net.

Due to changes in xUnit we've had to change the exception type thrown by our FunctionalAssert methods
from AssertActualExpectedException to XunitException.

Funcky.Analyzers

The new analyzer rule λ1009 prevents you from accidentally default-instantiating
Either, Result and EitherOrBoth.

Funcky.Async

The PowerSet and WithPrevious extensions now correctly pass along the cancellation token.

Funcky 3.4.0 | Funcky.Async 1.3.0 | Funcky.XUnit 2.0.2

30 Apr 03:30
56222df
Compare
Choose a tag to compare

This update is mainly to update to .NET 8 but also has several smaller improvements.

Native AOT

Both Funcky and Funcky.Async have been annotated to be compatible with Native AOT.
The only exception is OptionJsonSerializer which is not compatible with Native AOT.

.NET 8

We use the new C#12 and .NET features in the code, and expose new features through our API.

  • .NET 8 added new overloads to their TryParse APIs. These changes are reflected in Funcky's ParseOrNone APIs.
    • ParseByteOrNone overloads with ReadOnlySpan<byte> and string?
    • ParseSByteOrNone overloads with ReadOnlySpan<byte>
    • ParseSingleOrNone overloads with ReadOnlySpan<byte>
    • ParseDoubleOrNone overloads with ReadOnlySpan<byte>
    • ParseDecimalOrNone overloads with ReadOnlySpan<byte>
    • ParseInt16OrNone overloads with ReadOnlySpan<byte>
    • ParseInt32OrNone overloads with ReadOnlySpan<byte>
    • ParseInt64OrNone overloads with ReadOnlySpan<byte>
    • ParseUInt16OrNone overloads with ReadOnlySpan<byte>
    • ParseUInt32OrNone overloads with ReadOnlySpan<byte>
    • ParseUInt64OrNone overloads with ReadOnlySpan<byte>
    • ParseNumberOrNone<TNumber> overloads
    • ParseOrNone<TParsable> overloads

String Extensions

We implemented a few of the IEnumerable extensions which are very useful on strings.

  • Chunk on string.
  • SlidingWindow on string.

Monads

  • Implemented UpCast for the monds Option, Either, Result and System.Lazy.
  • Implemented InspectEmpty on IEnumerable and IAsyncEnumerable
  • Implemented ToAsyncEnumerable extension on Option

IEnumerator

  • MoveNextOrNone extension on IEnumerator<T>

Consistency

  • FindIndexOrNone and FindLastIndexOrNone extensions on List

What's Changed

Full Changelog: 3.3.0...3.4.0

Funcky 3.3.0 | Funcky.Analyzers 1.3.0 | Funcky.Xunit 2.0.1

14 Jul 10:14
bf99212
Compare
Choose a tag to compare

This is a relatively minor release focusing on convenience for our monads Option, Either and Result.

GetOrElse and OrElse for all

We've added GetOrElse and OrElse to Either and Result bringing them on par with Option.
The corresponding analyzer now also correctly suggests using these methods instead of Match for Result and Either.

Inspect for the error case

All three alternative monads Option, Either and Result now support inspecting the «error» case:

  • Option.InspectNone - executes a side effect only when the option is None.
  • Either.InspectLeft - executes a side effect only when the either is on the Left side.
  • Result.InspectError - executes a side effect only when the result is an Error.

These methods are particularly useful for logging warnings/errors.

Funcky 3.2.0 | Funcky.Async 1.2.0

17 May 09:10
b735e84
Compare
Choose a tag to compare

List Pattern for Option

We've added support for C# 11's List Patterns to Option<T>.
This means that you can use regular switch expressions / statements to match on options:

var greeting = person switch
{
    { FirstName: var firstName, LastName: [var lastName] } => $"Hello {firstName} {lastName}",
    { FirstName: var firstName } => $"Hi {firstName}",
};

record Person(string FirstName, Option<string> LastName);

Discard

The new Discard.__ field provides a short-hand for Unit.Value to be used with switch expressions.

using static Funcky.Discard;

return __ switch
{
    _ when user.IsFrenchAdmin() => "le sécret",
    _ when user.IsAdmin() => "secret",
    _ => "(redacted)",
};

Retry with Exception

We've added overloads to the Retry and RetryAsync functions that allow retrying a function
as long as an exception is thrown.

Example from IoRetrier:

// Retries an action until the file is no longer in use.
Task RetryWhileFileIsInUseAsync(IRetryPolicy policy, Action action)
    => RetryAsync(ActionToUnit(action), exception => exception is IOException && exception.HResult == FileInUseHResult, policy);

Funcky 3.1.0 | Funcky.Async 1.1.0 | Funcky.Analyzers 1.2.0

16 Nov 09:59
00c00cc
Compare
Choose a tag to compare

New APIs

  • OptionExtensions.ToNullable
  • StreamExtenions.ReadByteOrNone
  • New overloads for ElementAtOrNone that take an Index.
  • New overload for JoinToString that takes an IEnumerable<string>.

.NET 7

  • .NET 7 added new overloads to their TryParse APIs. These changes
    are reflected in Funcky's ParseOrNone APIs.
  • The ParseOrNone methods include the new [StringSyntax] attribute from .NET 7.

Analyzers

The new Option.Match analyzer suggests simpler alternatives over custom Matches including
the all-new ToNullable extension.

Funcky 3.0.0 | Funcky.Async 1.0.0 | Funcky.XUnit 2.0.0

14 Sep 07:59
c2739cf
Compare
Choose a tag to compare

There's a handy Migration Guide available.

New APIs

  • Result.GetOrThrow
  • EnumerableExtensions.GetNonEnumeratedCountOrNone

PriorityQueue

  • PriorityQueueExtensions.DequeueOrNone
  • PeekOrNone

Traversable

The new Traverse and Sequence extension methods allow you to
«swap» the inner and outer monad (e.g. Result<Option<T>> -> Option<Result<T>>)

Memoize

The new Memoize extension function returns an IBuffer / IAsyncBuffer.
This new type represents ownership over the underlying enumerator (and is therefore IDisposable).

CycleRange and RepeatRange have also been changed to return an IBuffer.

ParseExtensions

The parse extensions have been improved with the goal of aligning more with the BCL.
Many of the changes are breaking.

  • The functions now use BCL type names instead of C# type names
    (e.g. ParseIntOrNone has been renamed to Parse)
  • The parameter names and nullability have been changed to align with the BCL.
  • Added HttpHeadersNonValidatedExtensions

IReadOnlyList / IReadOnlyCollection

Funcky now communicates materialization in the IEnumerable<T> extensions by returning
IReadOnlyList or IReadOnlyCollection. This reduces «multiple enumeration» warnings.

  • Materialize
  • Chunk
  • Partition
  • Shuffle
  • SlidingWindow
  • Split
  • Transpose
  • Sequence.Return

Disallowing null Values

Our Option<T> type has always disallowed null values.
This has been extended to our other monads: Result<T>, Either<L, R> and Reader<E, R>.

Breaking Changes

  • Option.None() has been changed to a property. There's an automatic fix available for this.
  • Our Match functions now differentiate between Func and Action.
    The Action overloads have been renamed to Switch.
  • The return type of EnumerableExtensions.ForEach has been changed to Unit.
  • Many parameter names and generic type names have been renamed in an attempt to unify naming across Funcky.
  • All Action extensions have been moved to a new class ActionExtensions.
  • EitherOrBoth has been moved to the Funcky namespace.
  • The retry policies have been moved to the Funcky.RetryPolicies namespace.
  • Partition returns a custom Partitions struct instead of a tuple.

Obsoleted APIs Removed

APIs that have been obsoleted during 2.x have been removed:

  • ObjectExtensions.ToEnumerable
  • Funcky.GenericConstraints.RequireClass and RequireStruct
  • All Try* APIs (TryGetValue, TryParse*, etc.). These APIs use the OrNone suffix instead.
  • Sequence.Generate has been superceded by Sequence.Successors
  • CartesianProduct

JSON Converter

We have removed the implicit System.Text.Json converter for Option<T>.
This means that you'll have to register the OptionJsonConverter yourself.
⚠️ Test this change carefully as you won't get an error during compilation, but rather at runtime.

Moved to Funcky.Async

All APIs related to IAsyncEnumerable and Task have been moved to the new Funcky.Async package:

  • AsyncEnumerableExtensions
  • Functional.RetryAsync -> AsyncFunctional.RetryAsync
  • Option<Task> and Option<ValueTask> awaiters

Funcky.Async

AsyncSequence

This class exposes all of the same factory functions as Sequence, but for IAsyncEnumerable:

  • Return
  • Successors
  • Concat
  • Cycle
  • CycleRange
  • FromNullable
  • RepeatRange

New IAsyncEnumerable extensions

We've worked hard towards the goal of parity between our extensions for IEnumerable and IAsyncEnumerable:

  • AdjacentGroupBy
  • AnyOrElse
  • AverageOrNoneAsync / MaxOrNoneAsync / MinOrNoneAsync
  • Chunk
  • ConcatToStringAsync
  • ExclusiveScan
  • InclusiveScan
  • Inspect
  • Interleave
  • Intersperse
  • JoinToStringAsync
  • MaterializeAsync
  • Memoize
  • Merge
  • NoneAsync
  • PartitionAsync
  • PowerSet
  • Sequence / SequenceAsync / Traverse / TraverseAsync
  • ShuffleAsync
  • SlidingWindow
  • Split
  • Transpose
  • WhereNotNull
  • WithIndex / WithLast / WithPrevious / WithFirst
  • ZipLongest

Funcky.Xunit

  • Breaking: The Is prefix has been dropped from assertion methods for consistency with
    XUnit's naming scheme for assertion methods.

Funcky 2.7.1

13 Jun 09:32
0f6fae2
Compare
Choose a tag to compare

Deprecations

  • Option.None<T>(): We originally introduced the Option.None<T> method as a future proof replacement to Option<T>.None for use in method groups,
    because Funcky 3 changes Option<T>.None to a property. This turned out to be confusing to users especially because both method are always suggested in autocomplete.

Funcky 2.7.0 | Funcky.XUnit 1.0.0 | Funcky.Analyzers 1.1.0

20 Apr 13:42
c1e9af2
Compare
Choose a tag to compare

This release is the last non-breaking release for Funcky before 3.0.

Deprecations

  • EnumerableExtensions.CartesianProduct will be removed in Funcky 3.
  • To align our naming with that of the BCL, the ParseOrNone methods
    that return a type that has a keyword in C# int, long, etc. use the name of the BCL type instead.
    Example: ParseIntOrNone becomes ParseInt32OrNone.
    The old methods will be removed in Funcky 3.
  • In preparation for Funcky 3 we deprecated Option<T>.None when used as method group. Use Option.None<T> instead.

New ParseOrNone extensions

With the help of a source generator we have added a lot of new ParseOrNone methods for various types from the BCL:

  • Unsigned integer types
  • DateOnly, TimeOnly
  • Version
  • Support for ReadOnlySpan<T> as input
  • ... and more

Convenience for Either and Result

  • Added implicit conversions for Either and Result.
  • Implement Inspect for Either and Result.
  • Added Partition for IEnumerable<Either> and IEnumerable<Result>.
  • Added ToString on Either and Result.
  • Implement ToEither on Option.

IEnumerable<T> extensions

  • AnyOrElse
  • Prefix sum: InclusiveScan and ExclusiveScan

Analyzers

This release adds two new analyzer rules:

  • λ1003: Warning when certain methods, such as Match are used without argument labels
  • λ1004: Warning that suggests .ConcatToString() over .JoinToString("")

Both of these warnings come with corresponding code fixes.

Funcky.Xunit

  • Breaking: Funcky.Xunit now uses the Funcky namespace, instead of Funcky.Xunit.
  • Add assertion methods for testing Either: FunctionalAssert.IsLeft and FunctionalAssert.IsRight.

Funcky 2.6.0 | Funcky.Analyzers 1.0.0

16 Dec 14:48
7685340
Compare
Choose a tag to compare

Analyzers

This release comes with a new package Funcky.Analyzers, which we'll use
to guide users to a better Funcky experience.

New extensions

  • Add extensions DequeueOrNone and PeekOrNone on Queue and ConcurrentQueue.
  • Add extension ConcatToString as an alias for string.Concat.
  • Add overload to WhereSelect with no parameter.
  • Add methods to convert from Either to Option: #439
    • LeftOrNone: Returns the left value or None if the either value was right.
    • RightOrNone: Returns the right value or None if the either value was left.
  • Extension functions for System.Range to allow the generations of IEnumerable<T>s from Range-Syntax:
    foreach(var i in 1..5) { }
    
    // negative numbers are not supported
    from x in 5..2
    from y in 1..3
    select (x, y)

Improvements to Sequence

  • Sequence.Return now accepts multiple parameters:
    Sequence.Return(1, 2, 3)
  • ⚠️ Sequence.Generate has been deprecated in favour of the newly added Sequence.Successors function
    which includes the first element (seed) in the generated sequence.

Improvements to Option

  • Add Option.FromBoolean to create an Option<T> from a boolean.

Improvements to Result

The behaviour of the Result.Error constructor has been changed regarding exceptions
with an already set stack trace. The original stack trace is now preserved.
Previously this resulted in the stacktrace being replaced (.NET < 5.0) or an error (.NET ≥ 5.0).

Improvements to Either

  • Add Either.Flip to swaps left with right.

Tooling

  • Funcky automatically adds global usings for the most important namespaces of funcky
    when the FunckyImplicitUsings property is set. This requires .NET SDK ≥ 6.0 and C# ≥ 10.0.
  • Funcky now supports trimming for self-contained deployments.
  • Option<T> now works with the new System.Text.Json source generation.
  • The Funcky package now supports Source Link and deterministic builds.
  • The symbols package is now finally working again.

2.5.0

29 Jun 09:23
f226df6
Compare
Choose a tag to compare

Reader Monad

This release includes the Reader monad including a bunch of factory methods
and convenience extensions.

public static Reader<Enviroment, IEnumerable<string>> DefaultLayout(IEnumerable<DateTime> month)
    => from colorizedMonthName in ColorizedMonthName(month)
       from weekDayLine in WeekDayLine()
       from weeksInMonth in month
        .GroupBy(GetWeekOfYear)
        .Select(FormatWeek)
        .Sequence()
       select BuildDefaultLayout(colorizedMonthName, weekDayLine, weeksInMonth);

Improved Action Extensions

Funcky now supports Curry, Uncurry and Flip for Actions too.
This release also adds the inversion of ActionToUnit: UnitToAction

More Extensions for IEnumerable<T>

  • Intersperse: Adds a given item in between all items of an enumerable.
  • JoinToString: Alias for string.Join.
  • WithPrevious: Similar to WithFirst/Last/Index but with the predecessor of each item.
  • ForEach: Add an overload to ForEach that accepts a Unit-returning Func.

Additional Factory Methods

  • EitherOrBoth.FromOptions creates an EitherOrBoth from two options.
  • Lazy.FromFunc creates a Lazy<T> from a Func.
    This is sugar over the Lazy<T> constructor, with the additional benefit of supporting type inference.
  • Lazy.Return creates a Lazy<T> from a value.
    This is sugar over the Lazy<T> constructor, with the additional benefit of supporting type inference.

Documentation Improvements

This release comes with a few small documentation improvements.
Funcky users will now also see the [Pure] attributes which were previously not emitted.