问题
Here's a function polymorphic in 3 types:
:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
and here a non polymorphic function:
:t Data.Char.digitToInt
Data.Char.digitToInt :: Char -> Int
If we apply the former to the latter, we get a function polymorphic in 1 type:
:t (.) Data.Char.digitToInt
(.) Data.Char.digitToInt :: (a -> Char) -> a -> Int
which means that (.)
was "instantiated" (I'm not sure this is the correct term; as a C++ programmer, I'd call it so) with b === Char
and c === Int
, so the signature of the (.)
that gets applied to digitToInt
is the following
(Char -> Int) -> (a -> Char) -> a -> Int
My question is: is there a way to have this signature printed on screen, given (.)
, digitToInt
and the "information" that I want to apply the former to the latter?
回答1:
You can do that using the TypeApplications
extension, which allow you to explicitly specify which types you want to use to instantiate type parameters:
λ :set -XTypeApplications
λ :t (.) @Char @Int
(.) @Char @Int :: (Char -> Int) -> (a -> Char) -> a -> Int
Note that the arguments must be in the exact order.
For functions that have a "regular" type signature like foo :: a -> b
, the order is defined by the order in which the type parameters first appear in the signature.
For functions that use ExplicitForall
like foo :: forall b a. a -> b
, the order is defined by whatever it is in forall
.
If you want to figure out the type specifically based on applying (.)
to digitToChar
(as opposed to just knowing which types to fill), I'm pretty sure you can't in GHCi, but I can highly recommend Haskell IDE support.
For example, here's how it looks for me in VSCode (here's the extension):
来源:https://stackoverflow.com/questions/65258061/can-i-print-in-haskell-the-type-of-a-polymorphic-function-as-it-would-become-if