Skip to content

Version 3 of Language-Ext released

Choose a tag to compare

@louthy louthy released this 14 Apr 22:32

Today I have decided to release version 3 of lang-ext, this has been running along as a beta for many months now and has been stable for all of that period and so although there was much more stuff I wanted to put into the release, I feel it's probably a good idea to get, what's been done so far, live.

The big change is a major refactor to the async types and behaviours - lots of bug fixes and a project to standardise the Async types and methods. Because of this standardisation project (which is ongoing) you may see some compilation errors due to changes in method names or arguments (when using named arguments).

In practice this will mean some manual fix ups, but once done you shouldn't see any problems from the changes in behaviour.

There are lots of bug fixes in the async types, but also in general, so if you're one of those people that couldn't use the beta for whatever reason, I would highly recommend that you migrate to v3.0.0 - I've been using much of this in production for many months.

The kind of compilation issue you may see is:

    Match(Some, None)

Becoming variously:

    Match(SomeAsync, None)
    Match(Some, NoneAsync)
    Match(SomeAsync, NoneAsync)

This is to reduce the chance of compiler misunderstanding when using the many variants of each type of Match, Map, Bind etc.

Also, some functions may have changed from say Match to MatchAsync and vice versa depending on the context.

The scale of improvements in the async story can't be understated, there are many bug fixes, but also a huge increase in the amount of async functionality added. Not least from new types like EitherAsync, FunctorAsync, BiFunctorAsync, ApplicativeAsync, MonadAsync

I am now leveraging the type-class/class-instance system and splitting the synchronous and asynchronous types - this puts a very powerful type-safe story in place for the core types and their class instances. But this has also lead to an enormous amount of typing as the fall-out from this means essentially creating an Async type for each synchronous type (Option and OptionAsync for example). The end goal is a very happy place where there's a mathematical relationship between sync and async, and powerful features that fall out of it by default (like benefits in the higher-kinds system which allows pairs of monads to be composed into a single type).

This will be worked on over the next 6 months or so and will gradually improve.

A similar project has begun to create a type-safe way of describing safe and unsafe types. Unsafe types are those that will hold and/or return null. This is in an earlier stage than the async updates - but will have similarly profound effects for the standardisation of the core types and the relationship between safe and unsafe types (i.e. a safe type can become unsafe, but not the other way around).

A quick run down of what I could see from the commit notes. This is not an exhaustive list by any means:

  • Improvements in the type-class discovery system for Record equality, ordering, etc.
  • Additional class instances that derive from the Eq, Ord, Functor, Applicative, and Monad type-classes
  • Seq and Map various fixes and performance improvements
  • Significant improvements to OptionNone
  • Addition of EitherLeft<L> and EitherRight<R> to make type inference easier with Either<L, R>
  • IgnoreBaseAttribute for Record types - stops the base type fields being used for any Record operations
  • Minor performance improvements for Record types
  • Bug fixes in Result and OptionalResult
  • Try has partition, succs, and fails like Either's partition, lefts, and `rights.
  • Tuple<,,> and ValueTuple<,,> Sum fixes
  • Additional constructors and Prelude functions for the Writer monad
  • Massive improvements to the Higher Kinds feature to have more reliable binding operations which mean more robust pairing of monadic types. Also understand the pairings between async types and async and non-async types, which removes the chance of the .Result being called on an async type just to make it compatible in the HKT system. NOTE: This may mean some of the functions for the HKT types disappear - causing compilation errors. This is a good thing, they didn't do what you thought they did and you'll need to come up with a better solution yourself
  • Sequence and Traverse added for Writer, Reader, State, and RWS monads when they're paired with enumerable monads like Seq, Lst, IEnumerable, etc.

There's probably lots more, if you have a few days you can check the merge; it's probably not that fun to read.

Thanks to all contributors who helped put this release together. This is the first part of the bigger picture where async and unsafe become distinct typed concepts, rather than just suffixes on method names and types. Watch this space 👍