在 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 关键字代替∀。

这个关键字的作用是,

  1. 它引入了新类型变量ma,作为全称量化。现在,通常 Haskell 只是假设尚未在同一(!)签名中提及的 any 类型变量是通用的。但是
  2. 它禁止在整个上下文范围内自动引入类型变量。这也包括 r = mzero :: m a,所以此时 GHC 知道它 而不是 应该引入 ma 作为新变量,但重新使用matest.
  3. 的签名相同