为什么这种类型变量不明确?

时间:2009-04-03 08:16:57

标签: haskell type-inference typeclass

Cabbage.hs:

module Cabbage where 
class Cabbage a
  where foo :: a -> String      -- the parameter is only present for its type,
                                -- the parameter value will be ignored
        bar :: String -> a
quux :: Cabbage a => String -> a
quux s = bar (s ++ foo (undefined :: a))

当我编译(使用ghc)时,我收到此错误消息:

Cabbage.hs:7:19:
    Ambiguous type variable `a' in the constraint:
      `Cabbage a' arising from a use of `foo' at Cabbage.hs:7:19-38
    Probable fix: add a type signature that fixes these type variable(s)

我不明白为什么a含糊不清。当然,第7行中的a与第6行中的a相同吗?我该如何解决这个问题?

或者,是否有更好的方法来声明每个实例的常量?

3 个答案:

答案 0 :(得分:11)

使用范围类型变量,您可以让GHC知道undefined :: a应该相同(否则a只是forall a. a的简写)。然后,必须明确表示格式化变量:

{-# LANGUAGE ScopedTypeVariables #-}
module Cabbage where 
class Cabbage a
  where foo :: a -> String      -- the parameter is only present for its type,
                                -- the parameter value will be ignored
        bar :: String -> a
quux :: forall a. Cabbage a => String -> a
quux s = bar (s ++ foo (undefined :: a))

答案 1 :(得分:2)

问题在于Haskell不知道Cabbagefoo对应的a实例。据我所知,它与(undefined :: a)中的aquux :: Cabbage a => String -> a中的quux :: Cabbage a => String -> a quux s = result where result = bar (s ++ foo result) 不匹配

假设这就是你想要的,你可以这样做:

{{1}}

这将foo和bar联系在一起,以便它为两者使用相同的实例,并且因为你实际上不需要foo的输入值,所以它最低点。我不知道有更好的方法来执行每个实例的常量。希望其他人会和谁一起来。

答案 2 :(得分:2)

你可以将多态部分作为函数提取出来

quux :: Cabbage a => String -> a
quux s = quux' undefined
    where quux' :: Cabbage a => a -> a
          quux' x = bar (s ++ foo x)