1
votes

The excellent PureScript book explains that

fullName :: forall r. Record (firstName :: String, lastName :: String | r) -> String
fullName person = person.firstName <> " " <> person.lastName

and then compares the Eff monad

import Prelude

import Control.Monad.Eff.Random (random)
import Control.Monad.Eff.Console (logShow)

main :: forall eff. Eff (console :: CONSOLE, random :: RANDOM | eff) Unit
main = do
  n <- random
  logShow n

My question is: Why doesn't the signature of main contain a -> before Unit i.e.

main :: forall eff. Eff (console :: CONSOLE, random :: RANDOM | eff) -> Unit

This would make it similar to the -> String as in the signature of fullName

An excerpt from the same chapter(emphasis mine):

main is a computation with side-effects, which can be run in any environment which supports random number generation and console IO, and any other types of side effect, and which returns a value of type Unit

.

1
Do you understand what it means that the kind of Eff is # ! -> * -> *?Chris Martin
A bit. I have reread it and it does inform my understanding. ThanksRAbraham

1 Answers

1
votes

One difference between both functions is that fullName has a parameter (before the ->). The function signature states that it takes some record and returns a string.

main does not take any parameters, because it is the "entry point" for an application, and it returns Eff. So main just returns one type. That type happens to have two type parameters.

Function parameters and type parameters look quite the same, but they are on different levels. Types that take parameters have a constructor and have their parameters applied to produce the actual type. It looks like function application, but on the type level! The "signature" of types is called kind... you can learn more about it, but think about it as "types of types".

Now Eff is a type that combines some effects and some "actual result". Its constructor is applied with an effect row as first parameter and the result type as second parameter. In the case of main, all it does is side-effects, so the "actual result" is Unit, which is basically nothing.

If the signature of main was:

main :: forall eff. Eff (console :: CONSOLE, random :: RANDOM | eff) -> Unit

that would imply that

  • Eff only takes some effect row as type parameter (which does not match the definition of Eff)
  • main takes that Eff as a parameter (but were would it come from?)
  • main returns just Unit