umeshu
umeshu

Reputation: 1

Type class constraint with multiple variables

I have a hard time to grasp the following type class constraint of a Monad Reader function, that receive multiple variables,

local :: MonadReader r m => (r -> r) -> m a -> m a  

How to correctly understand the type class constraint? which one is the type constructor, r or m or both? (from the m a part it suggests the type constructor is m).

Compared with for example the bind function, where the type class constraint admitted only single parameter;

(>>=) :: Monad m => m a -> (a -> m b) -> m b 

Unlike the local function above, it's obvious and easy to comprehend that the type class constraint for the bind function demand type constructor m to be a Monad instance.

Upvotes: 0

Views: 436

Answers (1)

Random Dev
Random Dev

Reputation: 52290

In those cases it's best to look at the class (MonadReader) here.

There you'll find this:

class Monad m => MonadReader r m | m -> r where

and quite a bit more.

So here m is some monad and r will be the thing you read from (MonadReader is a so called monad-transformer ... well ok not quite - it's the class that is common to all those transformers - ReaderT is the transformer ... but that's really horrible to explain ... sorry)

local is used to change the thing you read from (I like to think of it as the configuration or the environment) - the r->r part - giving you a computation in the monad m that will do this change.

And if you read on in the documentation there is even an example of how to use this:

calculateContentLen :: Reader String Int
calculateContentLen = do
    content <- ask
    return (length content);

-- Calls calculateContentLen after adding a prefix to the Reader content.
calculateModifiedContentLen :: Reader String Int
calculateModifiedContentLen = local ("Prefix " ++) calculateContentLen

main = do
    let s = "12345";
    let modifiedLen = runReader calculateModifiedContentLen s
    let len = runReader calculateContentLen s
    putStrLn $ "Modified 's' length: " ++ (show modifiedLen)
    putStrLn $ "Original 's' length: " ++ (show len)

as you can see local is used here to add "Prefix " in front of the string

please note that the monad m in this example is not IO - it's Identity (basically nothing - it has no effect)


(I hope it's ok to copy and paste it ... if not please let me know or remove it)

Upvotes: 2

Related Questions