我想创建自己的名为Nodes的列表数据结构。然后,我将使用包含“ toList”功能的ListConverter类,并创建其实例。
data Nodes a = Empty
| Node a (Nodes a)
class ListConverter a where
toList :: a -> [Integer]
instance (Integral a) => ListConverter (Nodes a) where
toList Empty = []
toList (Node x Empty) = [x]
toList (Node x y) = x : toList y
GHCi告诉我,期望的类型为“整数”,但当前为“ a”。我非常困惑,因为在这种情况下,我为(Integral)提供了一个类型。这是错误消息:
error:
* Couldn't match expected type `Integer' with actual type `a'
`a' is a rigid type variable bound by
the instance declaration
at main.hs:7:10-48
* In the expression: x
In the expression: [x]
In an equation for `toList': toList (Node x Empty) = [x]
* Relevant bindings include
x :: a (bound at main.hs:9:18)
toList :: Nodes a -> [Integer] (bound at main.hs:8:5)
|
9 | toList (Node x Empty) = [x]
| ^
答案 0 :(得分:4)
您的ListConverter实例应接受“ a”的类Integral的任何值,但是Integer是特定类型,而不是类。您必须这样做:
index.html
或者相反,使您的ListConverter类能够生成Nodes值包含的任何类型的列表:
document.addEventListener('DOMContentLoaded', function() {
M.AutoInit();
});
(toList的第二个等式-(节点x空)-是不必要的)
答案 1 :(得分:1)
此实例的问题非常简单。您已签名:
toList :: a -> [Integer]
但是您尝试的实例实际上具有类型Nodes a -> [a]
。除非a
是Integer
类型,否则这是行不通的-但是您已经宣称它适用于所有Integral a
。其中包括其他类型,例如Int
。
一种解决方案就是限制您的实例:
instance ListConverter (Nodes Integer) where...
这是可行的-但我认为并没有真正尊重您可能打算上课的精神。
我认为最好的解决方案是认识到列表和您的Nodes
类型都被另一种类型所参数化,并以在通用基类上进行转换的方式定义该类。听起来比实际要复杂,
class ListConverter l where
toList :: l a -> [a]
然后,您可以编写instance ListConverter Nodes where...
,只需复制现有的toList
定义。 (我要指出的是,中间的一行是多余的。)