himekami
himekami

Reputation: 1459

Is this a type declaration?

Haskell newbie here. I was following this generative art tutorial over the net and came across the following code snippet. I ran it and it works just fine. The thing is I don't understand any bit of it.

type Generate a = RandT StdGen (ReaderT World Render) a

Is it a product type declaration ? if it is then is it possible to combine a group of types in parentheses like the above ? The way I see, it looks more like a function defined in a type or something like that.

Upvotes: 1

Views: 125

Answers (2)

Jon Purdy
Jon Purdy

Reputation: 54979

Since no one has mentioned it so far, the term you’re looking for is monad transformer. Monad transformers let you add various effects on top of an existing type of actions. Examples include ReaderT, StateT, and MaybeT. So in your example you have:

  • Render is a Monad that describes rendering actions.

  • ReaderT World is a monad transformer; when applied to a monad, it produces a monad that can read an immutable environment of type World. So ReaderT World Render is a monad that describes Render actions, and also stores a World that can be read with ask or asks inside actions of this type, e.g., world <- ask.

  • RandT StdGen is a monad transformer which equips a monad with a random number generator of type StdGen (a standard generator), which you can access using the methods of MonadRandom: getRandom, getRandoms, getRandomR, and getRandomRs. So RandT StdGen (ReaderT World Render) is a monad that can render things, read the state of the World, and generate random numbers from a StdGen, e.g., dieRoll <- getRandomR (1, 6).

The type declaration just defines Generate as an alias for RandT StdGen (ReaderT World Render), with one type parameter a that indicates the result type of Generate actions. Anywhere you see Generate Foo, the compiler directly substitutes RandT StdGen (ReaderT World Render) Foo.

Upvotes: 2

Dan Robertson
Dan Robertson

Reputation: 4360

I think it isn’t obvious how to parse this so let’s break it up

type
Generate a
=
RandT
  StdGen
  (ReaderT
    World
    Render)
  a

So let’s break it down. Line 1 is type this means “I’m here defining a type alias”. A type alias is a shorthand for another type and is exactly the same as the type it expands into. Note that data means “I’m defining a new datatype and this is how to construct its values”.

Line 2 says “this type will be called Generate and is a has parameter a” that is the thing Generate is a function from some type-level thing (in this case types e.g. Int or Maybe Int and not e.g. Maybe)

Line 4 says that this type is equal to some application of the type constructor RandT. This thing has kind * -> (* -> *) -> * -> * and it’s meaning is roughly:

  1. The first argument is the type of the random number generator
  2. The second argument is some Monad
  3. A Monad is returned (I.e. the third argument is the type inside the Monad and the result is the Monad)

Let’s look at the second argument. This is an application of ReaderT, a type-level thing of kind * -> (* -> *) -> * -> *. The first argument is the thing you want to be able to read (the state of the world). The second is some Monad you want to be based on. In this case Render which I assume let’s you build up the art as as you go. There is no third so just like currying in normal Haskell, the result of this has kind * -> *, which is the kind that was wanted by RandT.

The way to read this is: Generate is a Monad that lets one use random number generation (with the standard generator), read a value of type World, and render art.

Upvotes: 8

Related Questions