Hi guys, newbie here.
I just started a pet project in PureScript. I’m working in Monad Transformers, and I’m running into something that drains my brain quite a bit, and I’m wondering how you would approach it.
Let’s say I’ve got a bunch of functions S that result in Effect (Maybe a)
, but I want to work in a MaybeT Effect a
. Now, for various reasons, I don’t want to change all the original functions S to be MaybeT Effect a
, because doing so will involve rewriting a bunch of code. So I create two functions hoistMaybe
and translateMaybe
. It wasn’t hard to google it and find a base on how to write these:
hoistMaybe :: forall a m. Maybe a -> MaybeT m a
translateMaybe :: forall a m. Effect (Maybe a) -> MaybeT Effect a
And that’s fine. I wish the nature of Monad Transformers allowed there to be a general solution, but sure, I can write a hoistX
and translateX
for every concrete Monad Transformer, nbd.
So using these functions, I’m able to implement a bunch of MaybeT Effect a
functions. So then I go to test, and I get to using Spec, where the tests are all written as Aff Unit
. Ah, crap. To keep the code easy for my brain to handle, I now need to be in MaybeT Aff a
, not MaybeT Effect a
. So I write the following functions so that I can use my MaybeT
functions in the same place, and then I write some tests:
-- I discard a Nothing as a testing failure
runMaybeAff :: forall a. MaybeT Aff a -> Aff Unit
-- Seems like I have to convert the results of my existing
-- functions using `runMaybeT` and translateMaybe`.
liftMaybeEffect :: forall a. MaybeT Effect a -> MaybeT Aff a
-- I also have some `Effect a` functions to run.
liftAffEffect :: forall a. Effect a -> MaybeT Aff a
-- Now I can write my test
it "does a thing" $ runMaybeAff do
a <- (doThing1 :: MaybeT Effect a) # liftMaybeEffect
b <- (doThing2 :: MaybeT Effect b) # liftMaybeEffect
-- Easy enough to write `lift`
a `shouldEqual` b # lift
-- Yet another lift function
liftAffEffect $ foreachE things \thing -> do
doThing thing `shouldEqual` 2
And I guess my question … is, is this the right way to do things? Cognitively, it’s not easy for me. Conceptually, all these things are for a similar purpose as lift
. But because PureScript doesn’t have function overloads, I can’t name them all lift
and let the compiler figure it out for me. I have to remember “what type” of function I’m using, and select the correct liftX
function based on that, and that makes the type inference less useful, and it makes me tired. Or is it just me?
And while it’s not great that I have to use a liftX
in most lines of the function, it seems necessary. It’s a relatively small price to pay, if the only function I ever had to type was lift
, with no variants. But that’s not true.
So I guess I’m just looking for feedback on my approach, and any other ways to lower cognitive load while programming in PureScript. I’m on VsCode with the PureScript plugin, but that’s about it. But maybe this is the kind of thing I should be expecting an IDE to handle.