1

以下是我正在尝试做的简化示例...

test :: Bounded a => Maybe a -> a
test (Just x) = x
test Nothing  = (maxBound :: a)

maxBound函数是多态的——类型类的方法之一Bounded。因此,当我使用它时,我需要指定Bounded我想要的版本。在这个简化的示例中,可以从上下文中推断出该类型——但在实际问题中它不能——显式类型在实际问题中是必需的,尽管在这里并非如此。

我的函数也是多态的。我不能直接指定具体类型,只能指定类型变量。适当的类型变量是a,我已经为其指定了Bounded a约束。

编译这个,我得到以下错误......

temp.hs:4:18:
    Could not deduce (Bounded a1) arising from a use of `maxBound'
    from the context (Bounded a)
      bound by the type signature for test :: Bounded a => Maybe a -> a
      at temp.hs:2:9-33
    Possible fix:
      add (Bounded a1) to the context of
        an expression type signature: a1
        or the type signature for test :: Bounded a => Maybe a -> a
    In the expression: (maxBound :: a)
    In an equation for `test': test Nothing = (maxBound :: a)

据我所知,这意味着ainmaxBound :: a被认为与a我想要的(函数签名中的类型变量)分开。a1是 GHC 发明的新名称,用于消除a它认为是分开的两个变量的歧义。GHC 认为ainmaxBound :: a表示它可以在此处使用任何类型(!),因此抱怨“任何类型”的限制不够。

这是使用(我认为)最新的 Haskell 平台中提供的 GHC 版本 7.6.3。

我以前也遇到过类似的问题,但总是与其他问题混在一起,所以一旦我解决了其他问题,问题就消失了。我认为它是由其他问题引起的而忽略了它。这里没有这样的奢侈 - 上面那个最小的例子并不是真正的问题,但它取决于完全相同问题的解决方案。

那么...为什么 GHC 将ainmaxBound :: a视为独立a于整个函数的类型变量?以及如何解决此问题以选择正确的版本maxBound

4

1 回答 1

3

主要问题实际上是,GHC 试图将功能视为

test :: forall a. Bounded a => Maybe a -> a
test (Just x) = x
test Nothing  = (maxBound :: forall a. a)

您需要 ScopedTypeVariables 扩展和重写函数来:

{-# LANGUAGE ScopedTypeVariables #-}

test :: forall a. Bounded a => Maybe a -> a
test (Just x) = x
test Nothing  = (maxBound :: a)

现在我们看到,内部a依赖于外部a

更新

如果您已经写好签名,则不需要任何扩展。

下一个功能工作正常!

test :: Bounded a => Maybe a -> a
test (Just x) = x
test Nothing  = maxBound
于 2013-11-10T17:19:44.220 回答