以下是我正在尝试做的一个简化示例......
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
的正确版本?
答案 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