我觉得这应该很容易,但我已经坚持了很长一段时间。
haskell是否可以为某些数据类型的列表创建类型类的实例?
我想要实现的目标如下。
class Rename a where
findSub :: a -> a
-- A 'normal' instance would look like this
instance Rename Atom where
findSub ......
-- Now i want to acchieve something like this
instance Rename ([] Atom) where
findSub ......
当我写这个时,我得到以下错误:
* Illegal instance declaration for `Rename [Atom]'
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use FlexibleInstances if you want to disable this.)
* In the instance declaration for `Rename ([] Atom)'
Failed, modules loaded: none.
我想知道如何解决这个问题以及为什么不允许这样做。
提前致谢。
答案 0 :(得分:3)
它只需要语言扩展,因为Haskell 98标准在技术上不允许这种形式的实例。当错误消息显示启用扩展时,通常只需执行此操作[1]。 #include <iostream>
using namespace std;
int** add(int** first, int** second);
int addAllElems(int** matrix);
int addAllElems(int** matrix);
void display(int** matrix);
int main()
{
int first** = {{5,7,4}, {3,9,2}, {7,3,6}};
int second** = {{3,7,2}, {6,2,6}, {3,5,8}};
cout << "The first matrix is:" << endl;
display(first);
cout << endl;
cout << "The second matrix is:" << endl;
display(second);
cout << endl;
cout << "The sum of the two matrices is:" << endl;
display(add(first, second));
cout << endl;
cout << "The sum of all elements of the first matrix is: "
<< addAllElems(first) << endl;
cout << endl;
return 0;
}
int** add(int** first, int** second) {
int[][] sum = new int[3][3];
for (int i = 0; i <= 2; i++) {
for (int j = 0; j <= 2; j++) {
sum[i][j] = first[i][j] + second[i][j];
}
}
return sum;
}
int addAllElems(int** matrix) {
int sumOfElems = 0;
for (int i = 0; i <= 2; i++) {
for (int j = 0; j <= 2; j++) {
sumOfElems += matrix[i][j];
}
}
return sumOfElems;
}
void display(int** matrix) {
cout << "[" << endl;
for (int i = 0; i <= 2; i++) {
for (int j = 0; j <= 2; j++) {
cout << matrix[i][j] << ", ";
}
cout << endl;
}
cout << "]" << endl;
}
是一个非常普遍且被接受的扩展,所以只需添加
In function 'int main()':
12:14: error: expected initializer before '*' token
63:1: error: expected '}' at end of input
位于文件顶部。
或者,通常可以定义这样的实例并递归地#34;在这种情况下,您不需要扩展,但除此之外,您可以免费获得更多实例,并且因为类型更多保证更一般。看看你是否可以定义
FlexibleInstances
相反,仅使用{-# LANGUAGE FlexibleInstances #-}
为instance (Rename a) => Rename [a] where
findSub ...
而非具体为a
的事实。当您可以通过这种方式定义实例时,这是一个很好的信号,表明您的设计是在正确的轨道上。
[1]有一些例外情况,例如Rename
或Atom
,有时表明您对类型类分辨率的工作原理有错误的想法。