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
?
The type of cast
is
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
.