Haskell数据类型实例作为运算符



我收到了一份关于haskell中数据类型的练习,但我不知道如何解决这个问题。

他们给了我一个数据,比如:data CatLista a = Nil | Unit a| Conc (CatLista a) (CatLista a) deriving Eq并且我需要使数据类型变为:Nil->[],单元x->[x] ,浓缩液->与(++(相同的操作员

因此,如果运行Conc (Unit 9)(Conc (Unit 5) (Unit 3)) == Conc (Conc (Unit 9) (Unit 5))(Conc (Unit 3) Nil),则应给出true,而Conc (Unit 9)(Unit 3) == Conc (Unit 3) (Unit 9)应给出false。

我已经尝试过这样实例化show类:

instance Show a => Show (CatLista a) where
show a = case a of
Nil -> []
Unit x -> "[" ++ show x ++ "]"
Conc Nil dos -> show dos
Conc uno Nil -> show uno 
Conc uno dos -> "[" + show uno ++ "," ++ show dos ++ "]"

我对haskell还很陌生,所以我可能不知道一些基础知识,因为我不明白为什么如果我用与下面的Conc (Unit 9)(Conc (Unit 5) (Unit 3)) == Conc (Conc (Unit 9) (Unit 5))(Conc (Unit 3) Nil)相同的命令运行它(返回Conc uno dos -> show uno ++ show dos(,它仍然返回False,即使很难,它们在我的show实例中都返回相同的[9][5][3]。

编辑

多亏了你,我做了它,它知道正确地返回像这个代码预期的值:

toLista :: Eq a => CatLista a -> [a]
toLista Nil = []
toLista (Unit x) = [x]
toLista (Conc a b) 
| a == Nil = toLista b 
| b == Nil = toLista a
| otherwise = (++) (toLista a) (toLista b)
instance (Show a,(Eq a)) => Show (CatLista a) where 
show a= show (toLista a)

但我仍然不知道为什么如果我尝试相同的比较,它仍然返回False,即使很难,我也会得到相同的结果[9,5,3]。

这可能是因为我对Haskell缺乏了解,对此感到抱歉。

如果两个值在调用show时产生相同的String,则这两个值是不等价的。(==) :: Eq a => a -> a -> Bool函数由Eq类型类实现。因此,您需要为自己的CatLista实现Eqinstance

如果使用deriving Eq,则Eq的默认实现是,如果两个值具有相同的数据构造函数,则它们是相同的,并且通过对它们调用(==),参数在元素上是等效的。

因此,您可以使用自己实现Eq的实例

data CatLista a = Nil | Unit a| Conc (CatLista a) (CatLista a) -- ← no deriving Eq
instance Eq a =>Eq(CatLista a) where
ca == cb= toLista ca == toLista cb

因为在数据声明中包含了deriving Eq,所以您要告诉编译器生成一个默认的相等方法。编译器无法读懂你的想法,也无法知道你打算通过子列表的串联来表示列表。

知道您打算Conc [1, 2] [3]代表与Conc [1] [2, 3]1相同的列表;两者中的任何一个都应被视为代表CCD_ 20。编译器不知道这一点。生成的等式方法看到,在一种情况下,我们在Conc构造函数的第一个字段中有[1, 2],而在另一种情况中,我们有[1]。这两个东西是不相等的,所以默认的相等方法说整个结构也不相等。

为了避免这种情况,请停止使用Show实例。Show用于将CatList转换为String的代码来构建它。它与测试相等性无关。不可能通过定义Show实例来更改==的结果。

您需要从数据声明中删除deriving Eq。这意味着编译器不会生成默认的相等方法,因此您可以编写自己的方法来执行不同的操作(比较两个CatLists是否表示相同的列表,而不是比较它们是否具有相同的结构(。


1我在这里滥用符号来使用括号语法编写子列表;这是不是的有效代码,我只是想让子结构中的差异更容易看到。

最新更新