Reputation: 805
If I want to compare types or just print type information in a Haskell source file, what options do I have?
Upvotes: 3
Views: 139
Reputation: 71400
A handy trick I've recently discovered is to use typed holes in combination with asTypeOf
1.
If you have code that does compile, and you want to know what the type of an expression within it is, replacing that expression with a hole sometimes messes things up, as in:
-- what is the type of this part, I wonder?
f xs = 3 * length xs
Replacing length xs
with a _
reports:
foo.hs:1:12: Warning:
Found hole ‘_’ with type: a
Where: ‘a’ is a rigid type variable bound by
the inferred type of f :: t -> a at foo.hs:1:1
length xs
is certainly not of type a
!
But if you use asTypeOf
, you can leave the length xs
there and insert a hole which has to have the same type as it:
f xs = 3 * (length xs `asTypeOf` _)
Now we get:
foo.hs:1:34: Warning:
Found hole ‘_’ with type: Int
Much better.
1 asTypeOf
is exactly the same as const
, in that it returns its first argument and completely ignores its second. However its type forces the second argument to be the same as the first; it's designed to be written infix with backticks.
It's designed for when you have an a sub-expression that's too polymorphic and GHC complains about ambiguous type variables; you could use an inline type declaration, but sometimes that's impossible without the ScopedTypeVariables
extension. If you have another value that is the correct type, you can use asTypeOf
to "select" the appropriate case from the polymorphic expression, without changing the value returned by the expression.
My use of it here is "backwards" from the intended case; I want the thing on the left to constrain type of the (ignored) hole on the right, rather than the other way around.
Upvotes: 4
Reputation: 116139
foo x = length [x] + _
Compiling with GHC or loading into GHCi will give:
Found hole ‘_’ with type: Int
Relevant bindings include
x :: a
foo :: a -> Int
Upvotes: 7