Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of * in the ReaderT Monad Transformer?

I am looking at the documentation for the Reader monad and ReaderT monad transformer.

The relevant definitions are:

newtype ReaderT k r m a :: forall k. * -> (k -> *) -> k -> *
type Reader r = ReaderT * r Identity

I don't understand what the * are doing in the definitions. In particular I am attempting to derive a new monad from ReaderT with IO as the base monad and a class constraint on the r value.

I am not sure why there is a fourth input to ReaderT (k) and what Reader is doing with that value when it puts a * in that position.

like image 231
John F. Miller Avatar asked Aug 15 '17 04:08

John F. Miller


People also ask

Why is Monad in Transformers?

Monad transformers not only make it easier to write getPassphrase but also simplify all the code instances.

What is the reader Monad?

The Reader monad (also called the Environment monad). Represents a computation, which can read values from a shared environment, pass values from function to function, and execute sub-computations in a modified environment. Using Reader monad for such computations is often clearer and easier than using the State monad.

What is liftIO?

liftIO allows us to lift an IO action into a transformer stack that is built on top of IO and it works no matter how deeply nested the stack is. We'll see some examples of this below.

What is a Haskell Monad?

What is a Monad? A monad is an algebraic structure in category theory, and in Haskell it is used to describe computations as sequences of steps, and to handle side effects such as state and IO. Monads are abstract, and they have many useful concrete instances. Monads provide a way to structure a program.


1 Answers

* is the kind of types with values : it stands for things like Int, List Int etc..

forall k means k is not necessarily of that kind. it stands for any kind of types, viewed as simply static things which you can declare and manipulate, but are not necessarily associated with runtime values. One example of this is when you want to 'decorate' some other type with extra information : the embroidering type has no reason to have any sort of value attached to it, it is "pure" information, to some embroided type (which usually have values)

More simply here, you can see that in Reader it all gets specialized to *, and m is specialised to the Identity monad. That's where you'd want your IO monad to be.

As for the constraints, it is best to not specify it in the type itself. Upon usage, where you use a particular method attached to the typeclass, it will get added on the fly. Indeed there are no reason expressions written which do not use a method should be burdened by requiring their callers to provide it.

(Unless you have a very good reason to, for deducing other instances, as in Dict where you capture a typeclass witness as a runtime value with a GADT, but that's probably not what you want to do)

like image 197
nicolas Avatar answered Sep 18 '22 17:09

nicolas