无法使用类型变量显式指定类型

时间:2013-11-10 00:37:53

标签: haskell

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

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)

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

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

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

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

1 个答案:

答案 0 :(得分: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