哈斯克尔| 无法从上下文中推断出来

Pet*_*lys 3 haskell

我有这个不编译的代码.我想明白为什么它不能推断出类型.

module Main where

data Combiner a = Combiner a (a -> Int)
comb = Combiner 3 (\x -> 5)

class HasValue a where
  getValue :: Int

instance HasValue Combiner where
  getValue (Combiner x f) = f x

main = print $ getValue comb
Run Code Online (Sandbox Code Playgroud)

这是错误:

main.hs:8:3: error:
• Could not deduce (HasValue a0)
  from the context: HasValue a
    bound by the type signature for:
               getValue :: HasValue a => Int
    at main.hs:8:3-17
  The type variable ‘a0’ is ambiguous
• In the ambiguity check for ‘getValue’
  To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
  When checking the class method:
    getValue :: forall a. HasValue a => Int
  In the class declaration for ‘HasValue’
Run Code Online (Sandbox Code Playgroud)

Wil*_*sem 6

鉴于我理解正确,你定义了错误的签名getValue.现在定义:

class HasValue a where
  getValue :: Int
Run Code Online (Sandbox Code Playgroud)

所以这意味着可以有不同的版本getValue,但由于这些都返回了Int,所以我们完全不可能知道instance我们想要选择哪个版本.

根据instance文件后面的声明(以及函数的名称),我认为你实际上在寻找:

class HasValue a where
  getValue :: a -> Int
Run Code Online (Sandbox Code Playgroud)

现在Haskell可以a从函数应用程序的参数类型派生出来.此外,这也与你的功能体相匹配instance HasValue.

此外,Combiner不是一个单型,所以我们需要在头部添加类型参数:

instance HasValue (Combiner a) where
  getValue (Combiner x f) = f x
Run Code Online (Sandbox Code Playgroud)

  • 但是还有另一个问题.`HasValue`实例应该是`实例HasValue(Combiner a)`,而不仅仅是`实例HasValue Combiner`. (2认同)