自定义类型类实例化:无法将预期类型“b”与实际类型“Int”匹配

时间:2017-11-23 12:49:47

标签: haskell

我目前正在尝试实现一个类型类,它允许我将任何自定义类型转换为Integral(这些类型都应该可以转换为索引或权重)。在这种特殊情况下,我想用它来确保给定八度音阶上的音符可以转换为钢琴键盘键的索引:

import Data.Int

class Convertible a where
  toIntegral :: Integral b => a -> b

data Note = Note Tone Int

instance Convertible Note where
    toIntegral (Note t o) = o * 12 + toIntegral t

然而,编译器抱怨我toIntegral的{​​{1}}实现不符合我的Note类型类。

Convertible

据我了解,当我将 • Couldn't match expected type ‘b’ with actual type ‘Int’ ‘b’ is a rigid type variable bound by the type signature for: num :: forall b. Integral b => Note -> b at src/Note.hs:11:5 • In the expression: octave * 12 + (num tone) In an equation for ‘num’: num (Note tone octave) = octave * 12 + (num tone) In the instance declaration for ‘Convertible Note’ • Relevant bindings include num :: Note -> b (bound at src/Note.hs:11:5) 函数约束为toIntegral时,它会将a -> Int函数的内容评估为Integral => b -> a -> b。现在我不明白什么是错的,因为Int实现了Integral类型类,对吧?

你能帮我理解我在这里做错了吗?

1 个答案:

答案 0 :(得分:2)

类型变量由调用者选择,而不是由被调用者选择。在您的情况下,toIntegral无法选择b,其来电者会这样做。根据其类型,所有这些用途必须键入检查

toIntegral (Note t o) :: Int
toIntegral (Note t o) :: Integer
toIntegral (Note t o) :: Word32
-- etc.

解决方案也是转换Int,即转换o,以便返回任何整数b,而不仅仅是Int

例如,fromIntegral o可以将o转换为任何Num类型,因此任何Integral类型。

无论如何,你确定你的toIntegral确实需要这种类型吗?