2

In the 2003 Scrap Your Boilerplate paper by Laemmel and SPJ there is a code snippet on page 3

mkT :: (Typeable a, Typeable b) => (b -> b) -> a -> a
mkT f = case cast f of
   Just g -> g
   Nothing -> id

and then the paper explains

That is, mkT f x applies f to x if x's type is the same as f's argument type

Following in the pattern of the preceding examples in the paper, I would think the type of cast f would have to be compared with the type Maybe (b -> b) for the above to evaluate to Just g, but this seems incorrect.

What is going on here with the signature of cast f?

afsmi
  • 167
  • 6

1 Answers1

4

The type of castis

cast :: (Typeable x, Typeable y) => x -> Maybe y

it produces Nothing if x and y are different types and Just argument if they are the same. Note that the result type, y must be determined from the calling context when cast is used. If it isn't, compilation fails with an unresolved overloading/ambiguous type variable error.

In this particular example, the types are function types, (b -> b) for the argument, and (a -> a) for the result. So

cast f :: Maybe (a -> a)

and mkT could also be written mkT = fromMaybe id . cast.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • `cast` inspects the `TypeRep` of `f` and compares it with the `TypeRep` of the demanded type. If the `TypeRep`s are the same, it returns `Just f`, otherwise `Nothing`. – Daniel Fischer Jul 07 '12 at 20:31
  • I think I see now. I was missing the basic notion of how right-hand typeclass constraints work. I want to accept your answer, but could you edit/clarify w.r.t. how `cast` in this example 'fills in' its right typeclass constraint with the right-hand portion `(a -> a)` of the signature of `mkT` (since `->` is right-associative)? – afsmi Jul 07 '12 at 21:55
  • The right-hand-side type must be determined by the calling context, like it must be for `read` (or `fromIntegral`, but there's type defaulting for that one). Does that clarify it? – Daniel Fischer Jul 07 '12 at 22:25
  • Yes, I had an "aha" moment when I looked a bit closer at the context of `cast` and realized I had no idea what was going on with `Typeable y`, and then I found an answer with the `read` example at http://learnyouahaskell.com/types-and-typeclasses – afsmi Jul 07 '12 at 22:42