I’ve got this type alias:
type Board a = ReaderT String (StateT String IO) a
I know that StateT has the kind * -> (* -> *) -> * -> * so it should get three parameters. But in the above example, StateT only receives String and the IO-Monad.
Now I’m wondering where the missing parameter is passed to StateT.
Same goes for IO which should get one parameter but doesn’t get any.
>Solution :
If you look at the definition of ReaderT, you will see that its second parameter is itself applied to its last parameter:
newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
^^^
right here
Which means that its second parameter m must have kind m :: * -> *. And this is exactly what you get if you apply only two, not three, parameters to StateT:
StateT :: * -> (* -> *) -> * -> *
StateT x y :: * -> *
(where x :: * and y :: * -> *)
When substituting the definition of ReaderT in your type Board, you’ll get:
(1) type Board a = ReaderT String (StateT String IO) a
-- Substituting ReaderT definition (pseudocode)
(2) type Board a = { runReaderT :: String -> StateT String IO a }
^^^^^^^^^^^^^^^^^^
Look, StateT has all its three parameters!