如何获取具有 Bounded 实例的类型的 maxBound

How to get the maxBound of a type that has a Bounded instance

以下 Haskell 代码无法编译:

getMaxBound :: (Bounded a) => a -> a
getMaxBound _ = maxBound :: a

我得到的错误如下:

Could not deduce (Bounded a1) arising from a use of ‘maxBound’
  from the context: Bounded a
    bound by the type signature for:
               getMaxBound :: Bounded a => a -> a
    at rot13.hs:3:1-36

为什么我无法在 Haskell 中获取有界类型的 maxBound?

理想情况下,我会像这样使用这个函数:

getMaxBound 3
> 9223372036854775807

getMaxBound 'c'
> '14111'

我觉得每次我有任何类型 a 有一个 Bounded 实例时,我应该能够获得该类型的 maxBound。

我错过了什么?

类型签名就足够了

由于签名已经限制了类型,可以在函数体中去掉:: a部分:

getMaxBound :: Bounded a => <b>a</b> -> <b>a</b>
getMaxBound _ = maxBound

类型签名指定函数的输入类型与函数输出的类型相同。

例如:

Prelude> getMaxBound (3 :: Int)
9223372036854775807
Prelude> getMaxBound 'c'
'14111'
Prelude> getMaxBound True
True
Prelude> getMaxBound LT
GT

使用 ScopedTypeVariables 扩展程序

我们也可以使用ScopedTypeVariables extension [Haskell-wiki],然后通过引用a类型的变量来实现:

{-# LANGUAGE <b>ScopedTypeVariables</b> #-}

getMaxBound :: <b>forall a .</b> Bounded a => a -> a
getMaxBound _ = maxBound <b>:: a</b>

Willem 的回答在这种情况下应该可以正常工作,但在更复杂的情况下也可能有用的替代方法是使用 -XScopedTypeVariables

如果您将 {-# LANGUAGE ScopedTypeVariables #-} 行添加到文件顶部,您的代码应该可以编译。

扩展的作用是允许您在内部范围内引用外部范围的类型变量。在您的代码中,a 在函数体中被隐藏,并且它与外部 a 之间没有任何联系,导致您失去 Bounded a 上下文!