2

我试图理解 haskell 错误消息,因为它们让新手程序员感到困惑。我能找到的最简单的例子是:

Prelude> 1 + True
<interactive>:2:3:
No instance for (Num Bool)
  arising from a use of `+'
Possible fix: add an instance declaration for (Num Bool)
In the expression: 1 + True
In an equation for `it': it = 1 + True

为什么编译器不考虑参数顺序而寻找(Num Bool) ?为什么在我定义以下内容后它会起作用?

instance Num Bool where (+) a b = True;
[...]
Prelude> 1 + True
True

仅当第二个参数也是(Num Bool) 时,如何确保(+)可以应用于( Num Bool)

4

3 回答 3

4

您会收到此错误消息,因为两者1都是+多态的——它们都可以用于不同的类型!

看一看:

Prelude> :t 1
1 :: Num a => a
Prelude> :t (+)
(+) :: Num a => a -> a -> a

所以两者1 和对类中的 任何类型+都有意义。因此,当您编写 时,如果有实例,则实际上可能是一个。事实上,你可以自己做:Num1 + Bool1 BoolBoolNum

instance Num Bool where
  fromInteger x = x /= 0
  (+) = (&&)
  ...

一旦你这样做,1 + True就会真正起作用。您还可以将数字文字用作布尔值:

*Main> 1 :: Bool
True
*Main> 1 + True
True

这也解释了为什么不管参数的顺序如何都会得到相同的错误:代码中唯一的实际问题是True--if 有效,其他一切也一样。

于 2013-10-30T22:09:38.633 回答
1

这是 Num 的约定,任何数字整数文字都可以转换为所需的类型。

通过您的声明,Haskell 在现实中尝试:

fromIntegral 1 + True

这可能会使用未定义的第一个参数调用您的布尔值(+)。但这没关系,因为您从不评估它。

试着这样写:

(+) a b = if a then True else False

你可能会看到一个错误。

于 2013-10-30T22:04:45.007 回答
0

如果您在以下命令中运行,则错误消息表明data Bool不是 的实例class Numghci

Prelude> :info Num
class Num a where
  (+) :: a -> a -> a
  (*) :: a -> a -> a
  (-) :: a -> a -> a
  negate :: a -> a
  abs :: a -> a
  signum :: a -> a
  fromInteger :: Integer -> a
    -- Defined in `GHC.Num'
instance Num Integer -- Defined in `GHC.Num'
instance Num Int -- Defined in `GHC.Num'
instance Num Float -- Defined in `GHC.Float'
instance Num Double -- Defined in `GHC.Float'

可以看到 aNum是一个可以加(+)、乘(*)、减等的东西(-)

由于 aBool不能像这样表现,它没有Num. 这解释了错误中的行,No instance for (Num Bool)因为(+)只能用于Num

你在做什么instance Num Bool where (+) a b = True是说现在 a 的Bool行为也像 a Num,所以你必须指定如何 aBool可以相加(+)、相乘(*)等。

我希望我以足够简单的方式解释。

于 2013-10-30T22:09:27.370 回答