Question on composing Readers with monadic bound values #1384
Replies: 4 comments
-
Thank you :-) So yeah, you've bumped into the lack of monad-transformers in This is the process (really avoid it though): public static Reader<ItemRepo, Eff<Unit>> Example(ItemId id) =>
GetItem(id)
.Bind(effect =>
Reader<ItemRepo, Eff<Unit>>(env =>
effect.Bind(
item => ProcessItem(item).Run(env).IfFail(unitEff)))); So, we run the outer monad ( Simply, different flavoured monads are not composable. You must group them into single-flavour expressions. Or, create 'super monads' that contain the effects of all the different flavours. One such 'super monad' is If you're new to language-ext then I'd probably advise going straight to The big benefit of In public static ReaderT<ItemRepo, Eff, Item> GetItem(ItemId itemId) =>
from repo in ReaderT.ask<Eff, ItemRepo>()
from item in liftIO(async () => await repo.GetById(itemId))
select item;
public static ReaderT<ItemRepo, Eff, Unit> ProcessItem(Item item) =>
throw new NotImplementedException();
public static ReaderT<ItemRepo, Eff, Unit> Example(ItemId id) =>
from item in GetItem(id)
from _ in ProcessItem(item)
select unit; Which, as you can see from the final function, allows for both The blog is a good guide to getting moving, but if you want to see a real-world example that does a similar thing to what you're trying, the take a look at the
This approach allows you to take the various monadic effects, glue them together, and then make a friendly domain-specific type that represents a subsystem in your application. It also cuts down on the amount of generics you need to type and allows for easy augmentation of functionality later (refactor friendly). This is a huge change for I hope that helps. |
Beta Was this translation helpful? Give feedback.
-
This is incredibly helpful and I greatly appreciate the detailed response! I actually am using V5 already, so this will make my life a lot easier as the concept makes a lot more sense now. I'll reference the Just out of curiosity though if you don't mind, is what I just ran into basically the same practical concept behind a construct like |
Beta Was this translation helpful? Give feedback.
-
I haven't used
So, instead of There are lots of transformer-types (see list below). You can stack as many as you like, so the possible combinations of effects is huge. You can roll your own too, you just need to implement
In future there will be a When you think of all the ways you could combine those types with the regular monads, it's clear it'd be impossible to manually compose all of those variants by hand. I think it would get pretty tedious too: It's best to build the two or three stacks your application needs, then create your domain monads from them. |
Beta Was this translation helpful? Give feedback.
-
Awesome, makes perfect sense! Thanks again for the assistance and the detail. |
Beta Was this translation helpful? Give feedback.
-
First off, @louthy, thanks for all you do with LanguageExt! As a .NET developer who's really enjoying functional programming, but has rarely found work in F#, LanguageExt is a life-saver.
My specific question has to do with composing Readers, but I'm sure there's a higher level concept I'm missing so I figure it's best to ask here.
Let's say I have the following method (I'll try to keep the example as simple as possible):
And I have another method I want to write with a signature like:
I'd like this second method to use the initial
GetItem
method to retrieve the item and then perform some operation on it that takes anItem
and results in anEff<Unit>
.Is it possible to do this using the
from .. in .. select
syntax that unwraps not only theReader
, but also the resultingEff
?I initially tried something like:
Sorry if the example is a bit non-sensical for this application, I'm really just more-so trying to understand the fundamental concepts at play, so any examples or assistance you can point to would be greatly appreciated.
Thanks in advance!
Beta Was this translation helpful? Give feedback.
All reactions