*
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)
ReaderT
isnewtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
. Thek
is only generated in the documentation by Haddock to emphasize the poly-kindedness ofReaderT
(-XPolyKinds
is enabled in the module where it is defined). – Alecr
value, not the derivation of a new type fromReaderT
withm
instantiated toIO
) I don't see why doing this would be impeded by the polykinded definition ofReaderT
. As @Alec states, thek
parameter is an artifact of haddock - in reality, it is entirely implicit, and you can pretend thatReaderT :: (* -> *) -> * -> *
(because it does indeed have that type). – user2407038