You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I just had a moment, whilst building the new monad-transformer functionality, where the elegance of the solution - that I have been working night and day to make - finally appeared. And, I felt like sharing!
What you see here is the ReaderT monad-transformer lifting a Maybe<int> (meaning we have a composition of Reader behaviour and Maybe behaviour - so we have an environment value we can access via ask and we have optional results).
Maybe<A> is just a test type, it won't be in the final release.
Other things you see here are:
Pure(123) - this generates a Pure<int> type, which is the new type for lifting a pure value into any monad. So we don't need things like SuccessEff, FinSucc, etc. just use Pure for everything.
use and release - all transducer based monads can acquire resources and will manage their lifetime automatically. If you don't call release or the computation fails before getting to the release call, the resource will automatically be freed.
ask<string>() - returns an Ask<Env, A> type that will work with any MonadReaderT derived type.
You can see the direct use of Maybe<int>.Just(100) in the LINQ expression. Unlike Haskell where the monad has to be manually lifted into the transformer, we can just use it directly and it all just works.
And, to show this isn't just a fluke, we can use any monad we like in the ReaderT transformer (and indeed, stack many of them, like Haskell). Below is the same example with Either.
And, what about if we want to define a regular Reader monad (which in Haskell is a ReaderT monad with the Identity monad lifted into it)? Well, we can do that too:
But of course, that Reader type is effectively working as an alias, so we can alias anything we want to make bespoke composed monads. For example, we can build domain specific monads:
// Domain monad - a composition of Reader (with a fixed AppConfig environment) and Either<Error, A>publicrecordApp<A>(Transducer<AppConfig,Monad<Either<Error>,A>>runReader):ReaderT<AppConfig,Either<Error>,A>(runReader);// Application environmentpublicrecordAppConfig(stringConnectionString,stringRootFolder);
NOTE: The casting is a little annoying, it isn't required as you can work with the raw ReaderT result, but makes the interface slightly more elegant. This will be one for the new source-genertors.
And once you have made your App monad, it becomes instantly usable in LINQ expressions and the like:
Another nicety is that because of the Drop all Async variants proposal (which is leading to a more 'green threads' approach), all monads - that you build using monad-transformers - will automatically have async support. Here's the above example with an async operation injected:
I still have a lot of typing to do to get everything in place. But., today was the first time I saw that the monad transformers can work in a way that isn't just a nightmare of generics, which means v5 is going to be a big leap in capability!
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I just had a moment, whilst building the new monad-transformer functionality, where the elegance of the solution - that I have been working night and day to make - finally appeared. And, I felt like sharing!
What you see here is the
ReaderT
monad-transformer lifting aMaybe<int>
(meaning we have a composition of Reader behaviour and Maybe behaviour - so we have an environment value we can access viaask
and we have optional results).Other things you see here are:
Pure(123)
- this generates aPure<int>
type, which is the new type for lifting a pure value into any monad. So we don't need things likeSuccessEff
,FinSucc
, etc. just usePure
for everything.use
andrelease
- all transducer based monads can acquire resources and will manage their lifetime automatically. If you don't callrelease
or the computation fails before getting to therelease
call, the resource will automatically be freed.ask<string>()
- returns anAsk<Env, A>
type that will work with anyMonadReaderT
derived type.Maybe<int>.Just(100)
in the LINQ expression. Unlike Haskell where the monad has to be manually lifted into the transformer, we can just use it directly and it all just works.And, to show this isn't just a fluke, we can use any monad we like in the
ReaderT
transformer (and indeed, stack many of them, like Haskell). Below is the same example withEither
.And, what about if we want to define a regular
Reader
monad (which in Haskell is aReaderT
monad with theIdentity
monad lifted into it)? Well, we can do that too:And that's it. Without writing any more code, I can use the
Reader
monad:But of course, that
Reader
type is effectively working as an alias, so we can alias anything we want to make bespoke composed monads. For example, we can build domain specific monads:And extend them with convenience methods:
And once you have made your App monad, it becomes instantly usable in LINQ expressions and the like:
Another nicety is that because of the Drop all
Async
variants proposal (which is leading to a more 'green threads' approach), all monads - that you build using monad-transformers - will automatically have async support. Here's the above example with an async operation injected:I still have a lot of typing to do to get everything in place. But., today was the first time I saw that the monad transformers can work in a way that isn't just a nightmare of generics, which means
v5
is going to be a big leap in capability!Party time :-)
Beta Was this translation helpful? Give feedback.
All reactions