GHC 9 中的“forall {..}”

Rei*_*ica 12 syntax haskell forall

这是 GHC 9 中的有效语法。这是什么意思(与GHC 8.10 此处要求的{..}不同)?(..)

ign :: forall {f :: Type -> Type} {p}. Applicative f => p -> f ()
ign _ = pure ()
Run Code Online (Sandbox Code Playgroud)

Ice*_*ack 11

6.4.14.1。推断变量与指定类型变量

自 9.0.1 版本以来,GHC 允许将用户编写的类型或种类变量标记为inferred,而不是默认的指定。通过将大括号中的类型变量绑定器写为{tyvar}or {tyvar :: kind},新变量将被归类为推断变量,而不是指定变量

  • ..指定类型
  • {..}推断类型

forall a.forall {a}.是 GHC 将通过统一自动实例化的不可见量词。

const :: forall a b. a -> b -> a
const a _ = a
Run Code Online (Sandbox Code Playgroud)

这意味着无需用户帮助即可const True EQ实例化a ( @Bool) 和b ( ) 。@Ordering

如果用户想要显式实例化它们,他们可以使用可见类型应用程序“覆盖它们的可见性”。这就是为什么它们是指定类型的原因。(尽管“特定可能是更准确的术语)

>> :set -XTypeApplications
>> :t const @Bool @Ordering True EQ
const @Bool @Ordering True EQ :: Bool
Run Code Online (Sandbox Code Playgroud)

如果出于某种原因我们只想指定b(而不召唤“蜗牛小队”:@_,嗯“部分类型签名”),我们可以将a设为推断类型。然后第一个类型被删除

const2 :: forall {a} b. a -> b -> a
const2 a _ = a

>> :t const2 @Ordering True EQ
const2 @Ordering True EQ :: Bool
Run Code Online (Sandbox Code Playgroud)

对于您的示例,这意味着 ghc 必须推断fp的类型。你不能写ign @IO @Int


当您具有善良的多态性时,这会变得更有用。如果你定义

-- MkApply @Type @[] @Int :: [Int] -> Apply @Type [] Int
-- MkApply @_    @[] @Int :: [Int] -> Apply @Type [] Int
type    Apply :: forall (k :: Type). (k -> Type) -> (k -> Type)
newtype Apply f a where
  MkApply :: forall (k :: Type) (f :: k -> Type) (a :: k). f a -> Apply @k f a
Run Code Online (Sandbox Code Playgroud)

实例化时必须指定k类型,但和MkApply @Type @[] @Int都隐含了这种类型。您可能更喜欢将k标记为 inferred,这样您就可以编写[]IntMkApplyMkApply @[] @Int

-- MkApply @[] @Int :: [Int] -> Apply @Type [] Int
type    Apply :: forall (k :: Type). (k -> Type) -> (k -> Type)
newtype Apply f a where
  MkApply :: forall {k :: Type} (f :: k -> Type) (a :: k). f a -> Apply @k f a
Run Code Online (Sandbox Code Playgroud)