对非参数化数据类型使用加号运算

enn*_*e87 2 haskell

我有一个包含"添加"操作的简单类

class (Eq a, Show a, Read a) => Group a where 
  add :: a -> a -> a
Run Code Online (Sandbox Code Playgroud)

我创建了一个名为"Z5"的新数据类型,其中包含一个构造函数参数,namly为int值:

data Z5 = Z5 Int deriving (Eq, Read, Show)   
Run Code Online (Sandbox Code Playgroud)

数据类型的实例化如下所示:

instance Group (Z5) where
  add x y = x+y
Run Code Online (Sandbox Code Playgroud)

问题是我收到错误消息:

 No instance for (Num Z5) arising from a use of `+'
 Possible fix: add an instance declaration for (Num Z5)
Run Code Online (Sandbox Code Playgroud)

我试过了

instance (Num Z5) => Group (Z5) where
 add x y = x+y
Run Code Online (Sandbox Code Playgroud)

但然后错误信息是:

 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)'
Run Code Online (Sandbox Code Playgroud)

use*_*038 5

这个错误很简单: No instance for (Num Z5) arising from a use of `+'.你需要一个'Num'实例Z5.你有几个选择:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Z5 = Z5 Int deriving (Eq, Read, Show, Num)   
Run Code Online (Sandbox Code Playgroud)

这会Num为您的类型创建一个与其相同的实例Int.或者,您可以手动编写实例,如果您不希望它与实例相同Num.

instance Num Z5 where
     (Z5 a) + (Z5 b) = Z5 (a + b + 5) -- you can do whatever you like here
Run Code Online (Sandbox Code Playgroud)

写约束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)
Run Code Online (Sandbox Code Playgroud)

然后你可以做以下事情:

>add ((Sum 4) :: Sum Z5) ((Sum 5) :: Sum Z5)
Sum {getSum = Z5 9}
Run Code Online (Sandbox Code Playgroud)

  • 我的意思是"Sum"类型; 我更改了评论以反映这一点. (2认同)