【问题标题】:Haskell | Could not deduce from context哈斯克尔 |无法从上下文推断
【发布时间】:2018-07-27 01:43:58
【问题描述】:

我有这段代码无法编译。我想了解为什么它不能推断类型。

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

这是错误:

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’

【问题讨论】:

  • getValue的签名不应该是a -> Int吗?
  • 这可能不是唯一的错误。有时从第一个开始是有意义的

标签: haskell


【解决方案1】:

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

class HasValue a where
  getValue :: Int

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

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

class HasValue a where
  getValue :: a -> Int

现在 Haskell 可以从函数应用程序的 参数 的类型派生a。此外,这也与instance HasValue 中的函数体相匹配。

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

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

【讨论】:

  • 不过还有另一个问题。 HasValue 实例应该是 instance HasValue (Combiner a),而不仅仅是 instance HasValue Combiner
  • 谢谢。另外,所有带 * 种的类型都是完全接地的吗?
  • @PetrasPurlys:重读后,我认为monotype这个词更合适,是的,那些是类型为*的类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多