在 haskell 中的表达式中键入 class 和绑定重用
type class and binding reuse inside expressions in haskell
我不太清楚为什么这两个中间表达式不进行类型检查。类型检查器似乎会为 m
的每次出现更新新的类型绑定。是否有允许在所有这些位置重复使用名称 m
的扩展?
test :: MonadPlus m => m a
test =
let r = mzero :: m a -- fails
in let r' :: m a = mzero -- fails
in mzero
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UnicodeSyntax #-}
test :: ∀ m a . MonadPlus m => m a
test =
let r = mzero :: m a
in let r' :: m a = mzero
in mzero
如果您不喜欢代码中的非 ASCII 字符,您也可以省略 -XUnicodeSyntax
并使用 forall
关键字代替∀。
这个关键字的作用是,
- 它引入了新类型变量
m
和a
,作为全称量化。现在,通常 Haskell 只是假设尚未在同一(!)签名中提及的 any 类型变量是通用的。但是
- 它禁止在整个上下文范围内自动引入类型变量。这也包括
r = mzero :: m a
,所以此时 GHC 知道它 而不是 应该引入 m
和 a
作为新变量,但重新使用m
和 a
与 test
. 的签名相同
我不太清楚为什么这两个中间表达式不进行类型检查。类型检查器似乎会为 m
的每次出现更新新的类型绑定。是否有允许在所有这些位置重复使用名称 m
的扩展?
test :: MonadPlus m => m a
test =
let r = mzero :: m a -- fails
in let r' :: m a = mzero -- fails
in mzero
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UnicodeSyntax #-}
test :: ∀ m a . MonadPlus m => m a
test =
let r = mzero :: m a
in let r' :: m a = mzero
in mzero
如果您不喜欢代码中的非 ASCII 字符,您也可以省略 -XUnicodeSyntax
并使用 forall
关键字代替∀。
这个关键字的作用是,
- 它引入了新类型变量
m
和a
,作为全称量化。现在,通常 Haskell 只是假设尚未在同一(!)签名中提及的 any 类型变量是通用的。但是 - 它禁止在整个上下文范围内自动引入类型变量。这也包括
r = mzero :: m a
,所以此时 GHC 知道它 而不是 应该引入m
和a
作为新变量,但重新使用m
和a
与test
. 的签名相同