When I try to use printtype function from Type.Showtype. I find that the type signature of printtype is:
printtype :: Showtype a => proxy a -> IO ()
The confusing thing here is the type of proxy a, it seems come from Data.Proxy, but I can't find any definition of proxy, it is obvious that is different to Proxy, because first letter of proxy is lower case. And I knew the first letter of data type cannot be lower case in Haskell, so proxy a is not a type, but why does it can appear in the type signature?
In general a proxy for a type a is some data type Proxy a whose values carries no information. So the value is passed around to as a witness for its type (for type inference / type checking purposes). In that case proxy is isn't a specific data type, but a type variable with kind * -> *. Meaning you can use whatever you want as a proxy, but the idea remains the same.
The function is,
printtype :: Showtype a => proxy a -> IO ()
and it is supposed to "print a type", but functions are applied to values not types. So rather than passing an actual an argument of type a you pass an argument of some type proxy a, whose actual value is irrelevant (and usually will be a data type Proxy that contains no information).
Look at the instance for a simple type, e.g. pairs,
instance (Showtype a, Showtype b) => Showtype '(a,b) where
showtype _ = showtuple' [
showtype (Proxy :: Proxy a),
showtype (Proxy :: Proxy b)]
First note how showtype ignores its argument,
showtype _ = ...
the value of the proxy is irrelevant, what matters is that we are printing the type (a,b). Then we have a call to showtuple', which is used to print types tuples (of any length) given a list with the printing of the types of each component. For each component we have,
showtype (Proxy :: Proxy a)
showtype (Proxy :: Proxy b)
the selected proxy here is the data type Proxy which holds no information. In one case it is of type Proxy a and in the other Proxy b. The function showtype is defined so that you could also call it with e.g.
showtype ([] :: [a])
showtype ([] :: [b])
Not that if you were passing around a rather than proxy a, here the only value you'd be able to construct (for a generic a) would be undefined. Should its evaluation ever be forced it would break your program.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With