GHCi具有:type <expr>
来显示表达式的类型:
Prelude> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
GHCi是否可以在替换任何类型变量后显示结果?例如,让f = ((->) c)
,然后
:t (<*>) :: ((->) c) (a->b) -> ((->) c) a -> ((->) c) b
(<*>) :: ((->) c) (a->b) -> ((->) c) a -> ((->) c) b
:: (c -> a -> b) -> (c -> a) -> c -> b
有没有办法让GHCi找出这些替代物?
答案 0 :(得分:8)
是的,有几种方法。许多操作都将其类型变量作为其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