Monad Transformer missing parameter (?) - haskell

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.

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!

You correctly observe that
StateT has the kind * -> (* -> *) -> * -> *
and the same is true of ReaderT.
So it takes 3 "parameters" as you call them. The first is String, of kind *, and the third is a, again of kind *. While the second must be of kind * -> *.
And that is given in your example by StateT String IO. So although there is in one sense a "missing parameter" of StateT, this needs to be "missing" in order to get something of kind * -> * - if you tried something like type Board a = ReaderT String (StateT String IO Int) a, this would fail with a "kind error", precisely because ReaderT's second type argument needs to be of kind * -> *, not of kind * which StateT String IO Int would have.
The same applies to why IO is used on its own rather than something of the form IO a. StateT String (IO Int) wouldn't work because StateT needs to apply to something of kind * -> * as its second type argument - IO has this kind but IO Int (or anything of the form IO a) does not.
To take a step back, monad transformers like ReaderT and StateT transform another monad, and a monad must always be of kind * -> *. IO is a monad, and so is StateT String IO. But IO Int and StateT String IO Int are not monads - and not for failing the monad laws or anything like that, but for a much more fundamental meaning, they are the wrong kind. (They are "concrete types" - types which have values - rather than "type constructors" that take another type as an argument.)

Related

Haskell: Function as Data type

I feel one of the mind hurdles in learning haskell is that data sometimes defines functions as data.
data Person = Person {
name :: String,
age :: Int
}
This is intuitive and resembles other languages. But in
newtype StateT s m a = StateT {
runStateT :: s -> m (a,s)
}
This is basically calling a function s->m (a,s) "data"
I can readily understand that in higher order functions, "functions" are indeed passed around as data. But in type definitions, using functions to define types, that's quite surprising.
So my question is: will this bring expressiveness to Haskell type system? What is the theory behind all this?
It's just a wrapper around a function.
foo :: String -> [(Int, String)]
foo xs = zip [1..] (map pure xs)
fooState :: StateT String [] Int
fooState = StateT foo
The data constructor StateT takes a single argument, a function of type s -> m (a, s), and returns a value of type StateT s m a. Here, we have
s ~ String
m ~ []
a ~ Int
due to the declare type of foo.
It's really not very different from a function reference in a language like Python. (Note that foo has a slightly different type here than in the Haskell example, but the idea of passing a reference to foo to StateT.__init__ is the important thing to note).
class StateT:
def __init__(self, f):
self.runStateT = f
def foo(xs):
return enumerate(xs)
x = StateT(foo)
Functions, like any other value, have types and, as you say, can be passed as arguments. Fields of data types can also store functions, which again is no different from how other values can be used:
GHCi> :t ("foo", "bar")
("foo", "bar") :: ([Char], [Char])
GHCi> :t (reverse, drop 2)
(reverse, drop 2) :: ([a1] -> [a1], [a2] -> [a2])
From this point of view, there is no essential difference between...
newtype MyInt = MyInt { getMyInt :: Int }
... and:
newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }
will this bring expressiveness to Haskell type system?
Here are two of the ways in which it does so. Firstly, wrappers and type synonyms for function types allow writing less cluttered type signatures. This, for example...
withStateT :: (s -> s) -> StateT s m a -> StateT s m a
... reads quite a bit nicer than:
withStateT :: (s -> s) -> (s -> m (a, s)) -> (s -> n (a, s))
Secondly, newtype wrappers make it feasible to write class instances for function types -- without them, for instance, we wouldn't have the crucially important instances that StateT has (Functor, Applicative, Monad, MonadTrans, etc.).

Higher kinded type on typeclass? [duplicate]

If I inspect the kind of Maybe I get this:
λ> :k Maybe
Maybe :: * -> *
Now, if I inspect the kind of Monad I get this:
λ> :k Monad
Monad :: (* -> *) -> Constraint
What is Constraint there and why it is needed ? Why not just this * -> * ?
Unlike Maybe, Monad is not a type; it is a typeclass.
The same goes for other typeclasses:
Num :: * -> Constraint
Functor :: (* -> *) -> Constraint
Bifunctor :: (* -> * -> *) -> Constraint
Where * represents concrete types (such as Bool or Int), -> represent higher-kinded types (such as Maybe), and Constraint represents the idea of a type constraint. This is why:
As we know we can't make a signature like this:
return :: a -> Monad a -- This is nonsense!
Because Monad should be used as a constraint, to say that, 'this must be a monad to work':
return :: (Monad m) => a -> m a
We do this because we know that return can't work on any old type m, so we define the behaviour of return for different types under the name Monad. In other words, there is no single thing that can be called a Monad, but only behaviour that can be called Monadic.
For this reason, we have created this type constraint, saying that we must have pre-defined something as a Monad to use this function. This is why the kind of Monad is (* -> *) -> Constraint - it itself is not a type!
Maybe is an instance of Monad. This means that somewhere, someone has written:
instance Monad Maybe where
(>>=) = ... -- etc
...and defined how Maybe should behave as a Monad. This is why we can use Maybe with functions or types that have the prefix constraint Monad m => .... This is essentially where one defines the constraint applied by Monad.
Constraint is the kind of e.g. Show Int, Monad Maybe, and Monoid [a]. Roughly, it is the kind of everything that can occur on the left side of => in type annotations.
Now since
Show Int :: Constraint
and Int is a type, i.e.
Int :: *
we can assign a functional kind to Show as follows
Show :: * -> Constraint
^-- the result kind
^-- the kind of Int
In your case it just happens that a Monad takes argument like Maybe, so
Maybe Int :: *
Maybe :: * -> *
Monad :: (* -> *) -> Constraint
^-- the result kind
^-- the kind of Maybe

Type does not get fully applied

I have following code snippet from haskell book:
embedded' :: MaybeT (ExceptT String (ReaderT () IO)) Int
embedded' = MaybeT (ExceptT (ReaderT (const (return (Right (Just 1))))))
The type signature of ExceptT is as follow:
newtype ExceptT e m a =
ExceptT { runExceptT :: m (Either e a)) }
Compare the type signature of the embedded' function with ExceptT type constructor:
ExceptT e m a
| | |
MaybeT (ExceptT String (ReaderT () IO) (**missing here**) ) Int
How can I just leave ExceptT as higher kinded?
I tried also:
fullType :: ExceptT String []
fullType = undefined
the compiler complains:
* Expecting one more argument to `ExceptT String []'
Expected a type, but `ExceptT String []' has kind `* -> *'
* In the type signature:
fullType :: ExceptT String []
Failed, modules loaded: none.
You probably got confused by outmost MaybeT. This type is parametrised by 2 arguments of kinds m :: * -> * and a :: *, respectively. So, that ExceptT String (ReaderT () IO) is indeed missing an a because it is an MaybeT first argument and should be of kind * -> *. Had we apply Int to ExceptT, it would turn into * and then it can't be passed to MaybeT.
Disclaimer: I am not with my Haskell environment, so this might be utter nonsense.
Put in an explicit type variable for the missing spot on ExceptT:
embedded' :: MaybeT (ExceptT String (ReaderT () IO) a) Int
embedded' = MaybeT (ExceptT (ReaderT (const (return (Right (Just 1))))))
Hopefully the compiler can figure out what a should be!
What you're running into, which shows more obviously in your fullType example, is that it's not possible to give something a type of kind * -> *. Functions, values and so forth all need to have types of kind *.
Currying a type constructor gives you a * -> *, so you have to provide something for all the parameters.
Putting a type parameter in the signature for embedded' makes it kind *, but polymorphic over a.

How do I solve this monadT relationship in Haskell?

I met this question today while learning haskell monad transformers.
Assume I have a type instance Monad m => Monad (CustomT m).
If there's a function f :: CustomT IO Int, and there's g :: IO (Maybe Int).
How do I access the Int of g in f?
I tried something like
f = do
mVal <- g
This didn't work because f is under CustomT IO monad while g is under MaybeT IO monad.
And then I tried
f = do
mVal <- return g
This seems to work but mVal is IO (Maybe Int) type, I eventually get nested IO like CustomT IO (IO something)
Is there a way to get that Int or Maybe Int out in f?
What knowledge is involved?
Thanks in advance.
In the general case, Jeremy's answer is what you want. But let's see if we can work with your specific case here. We have f :: CustomT IO Int and g :: IO (Maybe Int), given that there exist some instances to the effect of instance Monad m => Monad (CustomT m) and instance MonadTrans CustomT.
And what you want is to get at the Int inside of a g within the context of CustomT IO. Since we're inside of CustomT, we can basically strip that layer off trivially. Like Jeremy says, use lift to get rid of that.
lift :: (MonadTrans t, Monad m) => m a -> t m a
So now we have CustomT IO (Maybe Int). Like I said, we're inside a do-block, so using Haskell's bind (<-) syntax gets rid of the monad layer temporarily. Thus, we're dealing with Maybe Int. To get from Maybe Int to Int, the usual approach is to use maybe
maybe :: b -> (a -> b) -> Maybe a -> b
This provides a default value just in case the Maybe Int is actually Nothing. So, for instance, maybe 0 id is a function that takes a Maybe Int and yields the inner Int, or 0 if the value is Nothing. So, in the end, we have:
f = do
mVal <- maybe 0 id $ lift g
-- Other code
In the Control.Monad.Trans you have this definition for monad transformers:
class MonadTrans (t :: (* -> *) -> * -> *) where
lift :: Monad m => m a -> t m a
Which means that if CustomT has been defined properly you can do this:
f = do
mVal <- lift g

Understanding `kind` of MonadTrans

Looking at the kind of Monad:
ghci>:k Monad
Monad :: (* -> *) -> Constraint
I believe that's because it takes an a from m a, and returns the Monad constraint.
Looking at MonadTrans's *kind, I see:
ghci>:i MonadTrans
class MonadTrans (t :: (* -> *) -> * -> *) where
lift :: Monad m => m a -> t m a
-- Defined in `Control.Monad.Trans.Class'
instance MonadTrans MaybeT
-- Defined in `Control.Monad.Trans.Maybe'
So, the first (* -> *) comes from Monad's kind, I believe. But what about the * -> *?
The second * -> * also comes from Monad's kind! A monad transformer takes a type argument that is a Monad (or at least a type that has the kind of a Monad) and produces a new type which is a Monad (which also has the kind of a Monad).
* -> * -- a Monad
(* -> *) -> * -> * -- Something that takes a Monad and makes a new Monad.
* -> * -- also a Monad

Resources