无法推断使用'>'

时间:2016-11-16 05:20:16

标签: haskell typeclass

我遇到了与我试图创建的类型类相关的编译时错误。

我的节目:

main = print "here"


class Tiger a where
  tigerWeight :: (Ord o) => a -> o

class Zoo a where
  tiger :: (Tiger t) => a -> t
  tigerHeavier :: a -> a -> Bool
  tigerHeavier x y =
    (tigerWeight (tiger x)) > (tigerWeight (tiger y))

给出了编译错误:

$ ghc zoo
[1 of 1] Compiling Main             ( zoo.hs, zoo.o )

zoo.hs:14:5: error:
    • Could not deduce (Ord a0) arising from a use of ‘>’
      from the context: Zoo a
        bound by the class declaration for ‘Zoo’ at zoo.hs:(10,1)-(14,53)
      The type variable ‘a0’ is ambiguous
      These potential instances exist:
        instance Ord Ordering -- Defined in ‘GHC.Classes’
        instance Ord Integer
          -- Defined in ‘integer-gmp-1.0.0.1:GHC.Integer.Type’
        instance Ord a => Ord (Maybe a) -- Defined in ‘GHC.Base’
        ...plus 22 others
        ...plus two instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the expression:
        (tigerWeight (tiger x)) > (tigerWeight (tiger y))
      In an equation for ‘tigerHeavier’:
          tigerHeavier x y
            = (tigerWeight (tiger x)) > (tigerWeight (tiger y))

zoo.hs:14:6: error:
    • Could not deduce (Tiger a1) arising from a use of ‘tigerWeight’
      from the context: Zoo a
        bound by the class declaration for ‘Zoo’ at zoo.hs:(10,1)-(14,53)
      The type variable ‘a1’ is ambiguous
    • In the first argument of ‘(>)’, namely ‘(tigerWeight (tiger x))’
      In the expression:
        (tigerWeight (tiger x)) > (tigerWeight (tiger y))
      In an equation for ‘tigerHeavier’:
          tigerHeavier x y
            = (tigerWeight (tiger x)) > (tigerWeight (tiger y))

zoo.hs:14:32: error:
    • Could not deduce (Tiger a2) arising from a use of ‘tigerWeight’
      from the context: Zoo a
        bound by the class declaration for ‘Zoo’ at zoo.hs:(10,1)-(14,53)
      The type variable ‘a2’ is ambiguous
    • In the second argument of ‘(>)’, namely ‘(tigerWeight (tiger y))’
      In the expression:
        (tigerWeight (tiger x)) > (tigerWeight (tiger y))
      In an equation for ‘tigerHeavier’:
          tigerHeavier x y
            = (tigerWeight (tiger x)) > (tigerWeight (tiger y))

这是为什么?似乎所有类型都应该是可以推断的。特别是:

  • ' X'并且' y'在动物园类型类中,因此应该支持“老虎”。方法

  • (虎x)在老虎'类型,由老虎'标记。方法的签名。

  • (tigerWeight(tiger x))因此应该能够应用,并且已知是“奥德”的成员。班级,由'tigerWeight'标记。方法的签名。

1 个答案:

答案 0 :(得分:4)

  

' X'并且' y'在动物园类型类中,因此应该支持“老虎”。方法

他们这样做,但不知道你想要的Tiger类型的居住者 。如果我们查看tiger的完整类型签名,

tiger :: (Zoo a, Tiger t) => a -> t

我们可以看到a将由您提供的参数tiger推断,但t会是什么?需要有一个特定的实例(你没有),它必须是明确的。

  

(虎x)在老虎'类型,由老虎'标记。方法的签名。

同样,没有Tiger的实例。或者,与OO术语说话,只有界面,但不是实现该界面的东西。

  因此,应该能够应用(tigerWeight(tiger x)),并且已知它是“奥德”的成员。班级,由'tigerWeight'标记。方法的签名。

Ord类型类比较大。您必须指定您想要的实例。它不清楚,你想要哪一个,因为它们都支持>

将其与read :: (Read a) => String -> a进行比较。只要您没有指定a,就不清楚如何解析字符串。

read "1" :: Int

会奏效,但

read "1" :: [Int]

应该失败。这个选择需要做。

顺便说一句,写tiger :: Ord a => a -> o没有敏感的方法,因为你无法创建任意Ord值。

话虽如此,你从错误的方面接近这个问题。 Tiger是一种非常特殊的动物。不需要typeclass

data Tiger = ...

之后,您可以编写一个返回实际重量的完全正常的函数:

type Weight = Int

tigerWeight :: Tiger -> Weight
tigerWeight t = ...

data Zoo = ...

tiger :: Zoo -> Tiger