If I am reading you correctly, all you need to get what you describe is the a -> m a function. Once you have that, it is trivial to go from (a -> b) to (a -> m b) as below:
f :: a -> b
return :: a -> m a
g :: a -> m b
g x = return ( f x )
The critical piece of monads is the ability to turn a generic (a -> m b) function into an (m a -> m b) function.
Essentially, if you have a two argument function whose output is your monadic structure, you can turn it into a function where both arguements are your monadic structure. This is useful because it enable compostability.
Since I'm pretty sure the above would confuse people who are not already familiar with monads, consider nullable types:
f :: a -> Nullable b
g :: b -> Nullable c
Suppose we want to compose these into a new function, h (switching to a more C like notation:
h :: a -> Nullable c
h(x){
maybeY = f(x)
if(maybeY == Null) return Null;
y=maybeY.get();
return g(y);
}
With monads, if you let g' be the "modified" version of g that we discussed above, this just becomes:
h(x) = g'(f(x))
In Haskell, this ' function is called =<<, and has its precedence set such that the above would be written as
h x = g =<< f x
Although you often see it written the other way:
h x = f x >>= g
Or with some nice syntactic sugar:
h x = do
y <- f x
g y
In this last case, you can notice it reads exactly like the C-like code, except there are no explicit null checks.
Another common example is lists. You have functions that take a value and return a list of values:
f :: a -> [b]
g :: b -> [c]
You want to apply g to every element of f and get a 1 dimensional list containing all of the results. This is commonly known as flatMap.
h :: a -> [c]
h(x) = f(x).flatMap(g)
This looks simple, because flatMap is already the monadic bind operator. We just gave it a different name.
Essentially, if you have a two argument function whose output is your monadic structure, you can turn it into a function where both arguements are your monadic structure. This is useful because it enable compostability.
Since I'm pretty sure the above would confuse people who are not already familiar with monads, consider nullable types:
Suppose we want to compose these into a new function, h (switching to a more C like notation: With monads, if you let g' be the "modified" version of g that we discussed above, this just becomes: In Haskell, this ' function is called =<<, and has its precedence set such that the above would be written as Although you often see it written the other way: Or with some nice syntactic sugar: In this last case, you can notice it reads exactly like the C-like code, except there are no explicit null checks.Another common example is lists. You have functions that take a value and return a list of values:
You want to apply g to every element of f and get a 1 dimensional list containing all of the results. This is commonly known as flatMap. This looks simple, because flatMap is already the monadic bind operator. We just gave it a different name.