我有一个包含“添加”操作的简单类
class (Eq a, Show a, Read a) => Group a where
add :: a -> a -> a
我使用一个构造函数参数创建了一个名为“Z5”的新数据类型,namly是一个int值:
data Z5 = Z5 Int deriving (Eq, Read, Show)
数据类型的实例化如下所示:
instance Group (Z5) where
add x y = x+y
问题是我收到错误消息:
No instance for (Num Z5) arising from a use of `+'
Possible fix: add an instance declaration for (Num Z5)
我用
尝试了instance (Num Z5) => Group (Z5) where
add x y = x+y
但是错误信息是:
Non type-variable argument in the constraint: Num Z5
(Use -XFlexibleContexts to permit this)
In the context: (Num Z5)
While checking an instance declaration
In the instance declaration for `Group (Z5)'
答案 0 :(得分:5)
此错误非常简单:No instance for (Num Z5) arising from a use of `+'
。您需要Z5
的'Num'实例。您有几种选择:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Z5 = Z5 Int deriving (Eq, Read, Show, Num)
这会为您的类型创建一个与Num
相同的Int
实例。或者,您可以手动编写实例,如果您不希望它与Num
的实例相同。
instance Num Z5 where
(Z5 a) + (Z5 b) = Z5 (a + b + 5) -- you can do whatever you like here
编写约束C T
C
是一个类型类而T
是一个单态类型总是毫无意义;这将是真的,在这种情况下你不需要编写约束,或者它将是false,在这种情况下它将不会编译。
更一般地说,Num
的任何实例都是一个数学组,所以你可以写:
-- This newtype is defined in Data.Monoid
newtype Sum a = Sum a
instance Num a => Group (Sum a) where
add (Sum a) (Sum b) = Sum (a + b)
identity = Sum 0
invert (Sum x) = Sum (-x)
然后你可以做以下事情:
>add ((Sum 4) :: Sum Z5) ((Sum 5) :: Sum Z5)
Sum {getSum = Z5 9}
答案 1 :(得分:4)
您的意思是直接在您的原始代码中使用+
Z5
类型,或者您是想写一个
instance Group Z5 where
add (Z5 x) (Z5 y) = Z5 (x+y)
+
操作仅适用于数字(即Num
类型类的实例),因此您无法自动将其用于自定义数据类型,例如Z5