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

Haskell Data Type Instance as operator

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

他们给了我这样的数据:data CatLista a = Nil | Unit a| Conc (CatLista a) (CatLista a) deriving Eq 我需要使数据类型变为: Nil -> [] , Unit x -> [x] , Conc -> same operator as (++)

所以如果你 运行 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。

我已经试过像这样实例化节目 class:

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 uno dos -> show uno ++ show dos)命令如下 Conc (Unit 9)(Conc (Unit 5) (Unit 3)) == Conc (Conc (Unit 9) (Unit 5))(Conc (Unit 3) Nil) 它仍然是 returns False even tough they both return the same [9][5][3] with my show instance.

编辑

多亏了你,我做到了,它正确地知道 returns 这些代码的预期值:

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)

但我仍然不知道为什么如果我尝试相同的比较它仍然 return 是错误的,即使很难我得到 return 相同的 [9,5,3].

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

如果在调用 show 时产生相同的 String,则两个值不等价。 (==) :: Eq a => a -> a -> Bool function is implemented by the Eq typeclass。因此,您需要自己为 CatLista 实现 Eqinstance

如果使用deriving EqEq的默认实现是两个值相同,如果它们具有相同的数据构造函数,并且通过调用[=19=,参数在元素方面是等效的] 关于这些。

因此您可以自己为 Eq 实现实例:

data CatLista a = Nil | Unit a| Conc (CatLista a) (CatLista a) -- ← no deriving Eq

instance Eq a => <strong>Eq</strong> (CatLista a) where
    <strong>ca == cb</strong> = toLista ca == toLista cb

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

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

为避免这种情况,请停止摆弄 Show 实例。 Show 用于将 CatList 转换为构建它的 String 代码。它与测试平等无关。您无法通过定义 Show 实例来更改 == 的结果。

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


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