Да, есть несколько способов.Многие операции делают свои переменные типа частью своего API, и вы можете наблюдать это, включив правильные параметры и задавая правильный вопрос.
> :set -fprint-explicit-foralls
> :t +v (<*>)
(<*>)
:: forall (f :: * -> *).
Applicative f =>
forall a b. f (a -> b) -> f a -> f b
На самом деле это не выглядит особенным, но говорит:кое-что важное: поскольку переменные типа forall
d не заключены в фигурные скобки, они могут быть объектом приложений типов.(Но вы должны доверять различию «фигурные скобки» / «не фигурные скобки» только в :t +v
запросах! Нормальный :t
хрупким способом обеспечивает доступность приложения типа, которое может измениться с версии GHC на GHCверсия.)
> :set -XTypeApplications
> :t (<*>) @((->) _)
(<*>) @((->) _)
:: forall {w} {a} {b}. (w -> a -> b) -> (w -> a) -> w -> b
Иногда вы найдете термин, в котором вы не можете использовать приложения типа таким образом.Например:
> :t +v \f x -> f <*> x
\f x -> f <*> x
:: forall {f :: * -> *} {a} {b}.
Applicative f =>
f (a -> b) -> f a -> f b
Здесь фигурные скобки указывают, что для применения типов нет доступных типов.Нам не повезло?Нет, мы все еще можем использовать типовые отверстия, чтобы заполнить только те части, которые нам интересны, и спросить GHC об остальных.
> :set -XPartialTypeSignatures
> :set -Wno-partial-type-signatures
> :t (\f x -> f <*> x) :: ((_ -> _) -> _)
(\f x -> f <*> x) :: ((_ -> _) -> _)
:: forall {w} {a} {b}. (w -> a -> b) -> (w -> a) -> w -> b