无法推断未使用参数的类型 - 如果使用参数则消失

时间:2014-04-28 10:33:42

标签: haskell ghc

我有一个程序给出了一组食谱,所需的输出将告诉我需要制作多少中间产品。

data Recipe = Recipe { name :: String
                     , ingredients :: [(Recipe, Int)]
                     } deriving (Eq)

instance Show Recipe where
        show Recipe{name=n} = show n

foldRecipes :: (Integral a) => [(Recipe, a)] -> (Recipe, a) -> [(Recipe, a)] 
foldRecipes acc r@(Recipe{ingredients=i}, n) = 
         acc ++ requirements [(recipe, fromIntegral count * n) | (recipe, count) <- i]

requirements :: (Integral a) => [(Recipe, a)] -> [(Recipe, a)] 
requirements m = 
        foldl foldRecipes m m

main = 
        let dough = Recipe{ name = "dough", ingredients = [(flour, 200), (water, 200)] }
            flour = Recipe{ name = "flour", ingredients = [] }
            water = Recipe{ name = "water", ingredients = [] }

        in putStrLn $ show $ requirements [(dough, 2)]

输出:[("dough",2),("flour",400),("water",400)

在我做这个的过程中,我遇到了以下版本不起作用的事实,有人可以解释原因吗?如果我使用明确的Int代替Integral a作为类型签名,那么它确实有效。

foldRecipes :: (Integral a) => [(Recipe, a)] -> (Recipe, a) -> [(Recipe, a)]
foldRecipes acc r@(Recipe{ingredients=i}, _) =
         acc ++ requirements i

输出:

test_unused.hs:10:30:
    Could not deduce (a ~ Int)
    from the context (Integral a)
      bound by the type signature for
                 foldRecipes :: Integral a =>
                                [(Recipe, a)] -> (Recipe, a) -> [(Recipe, a)]
      at test_unused.hs:8:16-76
      `a' is a rigid type variable bound by
          the type signature for
            foldRecipes :: Integral a =>
                           [(Recipe, a)] -> (Recipe, a) -> [(Recipe, a)]
          at test_unused.hs:8:16
    Expected type: [(Recipe, a)]
      Actual type: [(Recipe, Int)]
    In the first argument of `requirements', namely `i'
    In the second argument of `(++)', namely `requirements i'
    In the expression: acc ++ requirements i

1 个答案:

答案 0 :(得分:4)

foldRecipes :: (Integral a) => [(Recipe, a)] -> (Recipe, a) -> [(Recipe, a)]
foldRecipes acc r@(Recipe{ingredients=i}, _) =
     acc ++ requirements i

上述方法不起作用,因为ingredients始终包含类型[(Recipe, Int)]的列表,而您的函数接受使用泛型整数类型Integral a的列表。 aInt是不同的类型,您无法使用++连接不同类型的列表。

您的其他版本的功能有效,因为您使用fromIntegralInt转换为更通用的类型。