With the two easy class libraries extracted and published to Nuget (Woz.SimpleIOC and Woz.Linq) it is time to move on to Woz.Functional. This will be a more iterative piece of work as I would like this library to have no dependencies and optional sub libraries/packages that carry the code with dependencies such as Woz.Functional.Immutable which will pull in the MS immutable collections and integrate them with Woz.Functional code.
My though here was go back to Haskell and CategoryTheory first principles and see if I could implement Functors, Monoids, Aplicative and the like for C# in a generic way. This would allow me to build every thing on top of these building blocks.
The sad truth is that C# is not capable of re-creating a Haskell like type system. Searching the web you will find many different attempts but in all cases they break down as the .NET/C# generic system is not capable of the Haskell type system subtlety. All the examples you will find are a compromised approximation that look fine in the various contrived examples but then all fall apart when pushed in the real world. For example, the simple definition of:
fmap :: (a -> b) -> Ma -> Mb
C# is just not capable of this definition in a generic means, you have no way to ensure the M in Ma is the same M in Mb, the generic type system treats each one as a separate type. This really forces you to declare a separate fmap declarations for each M to ensure the output boxing type us the same as the input one, such as:
IEnumerable FMap<T, TResult>(IEnumerable source, Func<T, TResult> selector);
IMaybe FMap<T, TResult>(IMaybe source, Func<T, TResult> selector);
This makes trying to build from first principles a bit pointless. I knew this was coming as the Monad library I built in BadlyDrawRogue went through this same fight. In that code I accepted the limitations in C# and instead decided that Linq integration was the better path. In C# Linq is really a monad and computational engine with IEnumerable being the only supplied monad. This means instead of the more normal naming of bind, return, map, fmap etc you instead use Linq naming such as Select, SelectMany etc.