# “Forall What?”

Getting GHCi to tell you the **real** inferred type of a subexpression

# What

Put this in your `.ghci`

.

`:def what \s -> pure ("let { it :: forall what. _; it = (" <> s <> ") } in it")`

Now when you want a quick way to get the inferred type of a

inside an `subexpression`

, enter `expression``:what `

and replace `expression`

with `subexpression``(`

.`subexpression` :: what)

# What?

Also, how?

If you’re trying to understand the type of an expression, particularly when dealing with a confusing type error, it’s helpful to be able to see the inferred type of a subexpression involving polymorphic terms.

For instance, earlier on in my Haskell career, one day during a code review I saw an expression like `f <$> g <$> xs`

, and I was surprised that it typechecked, because I remembered that the `<$>`

operator is **left**-associative, meaning that this was being parsed as `(f <$> g) <$> xs`

and not what my coworker had meant to write, `f <$> (g <$> xs)`

. In other words, `fmap (fmap f g) xs`

was accepted where `fmap f (fmap g xs)`

was intended, and I wanted to find out why. (Actually, in this case I figured it out by rephrasing the code with `fmap`

, but if it would come in handy later, I wanted to figure out how I could’ve figured it out.)

So my first thought was to use a type wildcard, since `PartialTypeSignatures`

were new at the time. In this case, asking GHCi about `fmap ((fmap :: _) f g) xs`

does tell us that the type is something like `(a -> b) -> (t -> a) -> (t -> b)`

, which contains the important bit for our purposes: `(t ->)`

is a `Functor`

. But there were other cases where this wasn’t helpful at all!

For instance, I was asked: why does `foldr id`

typecheck? If you ask GHCi about `(foldr :: _) id`

and `foldr (id :: _)`

, it will say, with perfect innocence and sincerity, that `foldr :: (a -> b -> b) -> b -> t a -> b`

and `id :: a -> a`

. These things you already knew—it gives you no insight. A partial type signature isn’t always quite enough to get GHCi to tell you the actual type at which a subexpression is being used. Part of the reason for this is by design: a partial signature shouldn’t over-constrain the type, so, as much as possible, the compiler will avoid saying anything it’dn’t’ve committed to if you hadn’t asked. We can sometimes wheedle the type by casually saying `… :: ()`

, in other words, “…, which (as you know) is a unit” and goading the typechecker into correcting us by saying, “Actually, that’s not a unit at all! It’s a —”. But that doesn’t always work: sometimes our trick backfires, and the typechecker just says “Yes, obviously.” because our annotation caused it to commit to that type: we’ve changed the outcome by trying to measure it. No good!

Fortunately, `ScopedTypeVariables`

give us a way to mint a fresh type variable, which, unlike some concrete type like `()`

, is guaranteed not to unify with anything else. In conjunction with a partial type signature, that lets us observe type inference without disturbing it.

`:{`

`let it :: forall what. _`

`it = ( (foldr :: what) id )`

`in it`

`:}`

`let { it :: forall what. _; it = ( (foldr :: what) id ) } in it`

And as I showed earlier, we can even make this into a GHCi command.

Now the typechecker will quit beating around the bush and tell us `what`

it expected…but alas, `((b -> b) -> b -> b) -> b -> t (b -> b) -> b`

it actually got. So sad! If we ask `:what foldr (id :: what)`

it laments the `(b -> b) -> b -> b`

that it has, which is not `what`

it wanted. That’s where we say “Poor thing—here, let me take those off your hands…” and make our getaway, with our pockets and purses jingling full of types.