So, in Haskell terminology, you want:
passAround :: Monad m => (a -> mb) -> a -> ma passAround fx = do fx return x
Read the type signature because " passAround accepts a function f :: a -> mb , the result of which is a monadic action (that is, that can have side effects that can be ordered in a specific order, thus Monad m ) with an arbitrary type result b and value a to pass this function. This gives a monadic action with result type a . "
To find out what this may mean, โfunctional programming construct,โ let us first expand this syntax. In Haskell, the notation for do is simply syntactic sugar for monadic combinators, namely
do foo bar
- sugar for foo >> bar . (This is a little trivial, it all really gets interesting when you also bind local results to variables.)
So,
passAround fx = fx >> return x
>> in itself is an abbreviation of the general operator of a monadic chain, namely
passAround fx = fx >>= const (return x)
or
passAround fx = fx >>= \y -> return x
(This backslash denotes a lambda function, in JavaScript it will read f(x) >>= (y)=>return x .)
Now, what you really want all this is a chain of several actions. In Javascript, you write g(passAround(f, x)) , in Haskell this is not just a function argument, because it is still a monadic action, so you want to use another monadic chaining operator: g =<< passAround fx or
passAround fx >>= g
If we expand passAround here, we get
(fx >>= \y -> return x) >>= g
Now, we can apply the laws of the monad , namely the law of associativity, giving us
fx >>= (\y -> return x >>= g)
and now the left unit law
fx >>= (\y -> gx)
IOW, the whole composition is minimized down to fx >> gx , which can also be written
do fx gx
... which is kind, duh. What of all this? Good, good, that we can abstract from this monadic rewriting with a monad transformer. In Haskell, it is called ReaderT . What would you do if you know that f and g use the variable x , you can exchange
f :: a -> mb g :: a -> mc
with
f' :: ReaderT amb f' = ReaderT f g' :: ReaderT amc g' = ReaderT g
The ReaderT value ReaderT conceptually matches your passAround function.
Note that ReaderT amc has the form (ReaderT am) c or, ignoring the details, m' c , where m' again a monad! And using the do syntax for this monad, you can simply write
runReaderT (do f' g' ) x
which in JavaScript would theoretically look like
runReaderT (() => { f'; g'; }, x)
Unfortunately, you cannot actually write it like this, because unlike Haskell, imperative languages โโalways use the same monad to sequence their work (which roughly corresponds to the Haskell IO monad). By the way, this is one of the standard descriptions of what a monad is: it is an overloaded comma operator .
However, what you can certainly do is implement the monad transformer on dynamic types in the functional part of the JavaScript language. I'm just not sure if this is worth doing.