haskell 如何确定隐式 forall 中类型变量的顺序?
How does haskell determine the order of type variables in implicit foralls?
所以我最近才了解并开始使用 TypeApplications
,并且想知道我们通常如何才能知道我们正在分配的类型变量。 The documentation on TypeApplications
I found 提及:
What order is used to instantiate the type variables?
Left-to-right order of the type variables appearing in the foralls. This is the most logical order that occurs when the instantiation is done at the type-variable level. Nested foralls work slightly differently, but at a single forall location with multiple variables, left-to-right order takes place. (See below for nested foralls).
但是我还没有找到关于如何确定隐式 foralls 中类型变量顺序的提及。我试着用 -fprint-explicit-foralls
查看不同的例子,看看是否有一个简单的模式,但我在不同版本的 ghci 中得到了不同的结果。 :/
在 ghci 版本 8.0.2 中,我得到:
> :t (,,)
(,,) :: forall {c} {b} {a}. a -> b -> c -> (a, b, c)
在 ghci 版本 8.4.3 中,我得到:
> :t (,,)
(,,) :: forall {a} {b} {c}. a -> b -> c -> (a, b, c)
然后,也许这只是 8.0.2 中打印 foralls 的一个错误,因为否则类型应用程序似乎使用 forall 的变量从右到左完成,这与文档所说的相反:
> :t (,,) @Bool
(,,) @Bool :: forall {c} {b}. Bool -> b -> c -> (Bool, b, c)
因此,类型变量是否始终按照它们在类型主体中从左到右出现的顺序(包括约束)放置在隐式 forall 中?
TL;DR: 类型变量顺序由第一次从左到右的相遇决定。如有疑问,请使用 :type +v
.
不要使用 :type
在这里使用 :type
会产生误导。 :type
推断整个表达式的类型。所以当你写 :t (,)
时,类型检查器会查看
(,) :: forall a b. a -> b -> (a, b)
并用新的类型变量实例化所有的 forall
(,) :: a1 -> b1 -> (a1, b1)
如果您申请 (,)
,这是必需的。唉,你没有,所以类型推断几乎完成了,它泛化了所有自由变量,你得到,例如,
(,) :: forall {b} {a}. a -> b -> (a, b)
此步骤不保证自由变量的顺序,编译器可以自由更改。
还要注意,这里写的是forall {a}
,而不是forall a
,意思就是不能在这里使用可见类型的应用。
使用:type +v
但是你当然可以使用 (,) @Bool
– 但这里类型检查器以不同的方式对待第一个表达式并且不执行此 instantiation/generalization 步骤。
您也可以在 GHCi 中获得此行为 – pass +v
to :type
:
:type +v (,)
(,) :: forall a b. a -> b -> (a, b)
:type +v (,) @Bool
(,) @Bool :: forall b. Bool -> b -> (Bool, b)
看,类型变量周围没有{…}
!
这个订单从哪里来的?
the GHC user's guide section on visible type application 状态:
If an identifier’s type signature does not include an explicit forall, the type variable arguments appear in the left-to-right order in which the variables appear in the type. So, foo :: Monad m => a b -> m (a c) will have its type variables ordered as m, a, b, c.
这仅适用于具有显式类型签名的事物。推断类型中的变量没有保证的顺序,但您也不能使用带有 VisibleTypeApplication
.
的推断类型的表达式
所以我最近才了解并开始使用 TypeApplications
,并且想知道我们通常如何才能知道我们正在分配的类型变量。 The documentation on TypeApplications
I found 提及:
What order is used to instantiate the type variables?
Left-to-right order of the type variables appearing in the foralls. This is the most logical order that occurs when the instantiation is done at the type-variable level. Nested foralls work slightly differently, but at a single forall location with multiple variables, left-to-right order takes place. (See below for nested foralls).
但是我还没有找到关于如何确定隐式 foralls 中类型变量顺序的提及。我试着用 -fprint-explicit-foralls
查看不同的例子,看看是否有一个简单的模式,但我在不同版本的 ghci 中得到了不同的结果。 :/
在 ghci 版本 8.0.2 中,我得到:
> :t (,,)
(,,) :: forall {c} {b} {a}. a -> b -> c -> (a, b, c)
在 ghci 版本 8.4.3 中,我得到:
> :t (,,)
(,,) :: forall {a} {b} {c}. a -> b -> c -> (a, b, c)
然后,也许这只是 8.0.2 中打印 foralls 的一个错误,因为否则类型应用程序似乎使用 forall 的变量从右到左完成,这与文档所说的相反:
> :t (,,) @Bool
(,,) @Bool :: forall {c} {b}. Bool -> b -> c -> (Bool, b, c)
因此,类型变量是否始终按照它们在类型主体中从左到右出现的顺序(包括约束)放置在隐式 forall 中?
TL;DR: 类型变量顺序由第一次从左到右的相遇决定。如有疑问,请使用 :type +v
.
不要使用 :type
在这里使用 :type
会产生误导。 :type
推断整个表达式的类型。所以当你写 :t (,)
时,类型检查器会查看
(,) :: forall a b. a -> b -> (a, b)
并用新的类型变量实例化所有的 forall
(,) :: a1 -> b1 -> (a1, b1)
如果您申请 (,)
,这是必需的。唉,你没有,所以类型推断几乎完成了,它泛化了所有自由变量,你得到,例如,
(,) :: forall {b} {a}. a -> b -> (a, b)
此步骤不保证自由变量的顺序,编译器可以自由更改。
还要注意,这里写的是forall {a}
,而不是forall a
,意思就是不能在这里使用可见类型的应用。
使用:type +v
但是你当然可以使用 (,) @Bool
– 但这里类型检查器以不同的方式对待第一个表达式并且不执行此 instantiation/generalization 步骤。
您也可以在 GHCi 中获得此行为 – pass +v
to :type
:
:type +v (,)
(,) :: forall a b. a -> b -> (a, b)
:type +v (,) @Bool
(,) @Bool :: forall b. Bool -> b -> (Bool, b)
看,类型变量周围没有{…}
!
这个订单从哪里来的?
the GHC user's guide section on visible type application 状态:
If an identifier’s type signature does not include an explicit forall, the type variable arguments appear in the left-to-right order in which the variables appear in the type. So, foo :: Monad m => a b -> m (a c) will have its type variables ordered as m, a, b, c.
这仅适用于具有显式类型签名的事物。推断类型中的变量没有保证的顺序,但您也不能使用带有 VisibleTypeApplication
.