在大学时,我们收到了编写函数的任务
> deleteNil :: Tree a -> Tree a
删除类型
树中每次出现的Nil > data Tree a = Nil | Leaf a | Br ( Tree a ) ( Tree a )
。
如果Tree只包含Nil,则返回值也应为Nil。
唯一的限制是,树的类型签名和函数deleteNil的签名都不允许被编辑,例如,我不被允许追加
deriving Eq, Show
到树a的类型签名。
我第一次尝试解决这个问题如下:
> deleteNil :: Tree a -> Tree a
> deleteNil Nil = Nil
> deleteNil (Br l r)
> | deleteNil l == Nil && deleteNil r == Nil = Nil
> | deleteNil l == Nil && deleteNil r /= Nil = r
> | deleteNil l /= Nil && deleteNil r == Nil = l
> | deleteNil l /= Nil && deleteNil r /= Nil = Br l r
但显然因为我不允许派生Eq这个版本给我编译错误
No instance for (Eq (Tree a)) arising from a use of '=='
。
我不想在这里要求找到这个问题的完整解决方案,但有人为我提供了一种新的方法,我应该如何尝试解决这个问题而不必比较树的部分?
答案 0 :(得分:2)
嗯,你几乎做对了,你错过的是你可以在l
和r
上进行模式匹配:
deleteNil :: Tree a -> Tree a
deleteNil Nil = Nil
deleteNil (Br Nil Nil) = Nil
deleteNil (Br l Nil) = (deleteNil l)
deleteNil (Br Nil r) = (deleteNil r)
deleteNil (Br l r) = case (deleteNil l, deleteNil r) of
(Nil, Nil) -> Nil
(nl, Nil) -> nl
(Nil, nr) -> nr
(nl, nr) -> Br nl nr
请注意功能中的Leaf
选项。
答案 1 :(得分:1)
您可以使用模式匹配:
deleteNil :: Tree a -> Tree a
deleteNil (Br l r) = case (deleteNil l, deleteNil r) of
(Nil, dr ) -> dr
(dl , Nil) -> dl
(dl , dr ) -> Br dl dr
deleteNil t = t
所以你不需要四个案例,因为这两个
| deleteNil l == Nil && deleteNil r == Nil = Nil
| deleteNil l == Nil && deleteNil r /= Nil = r
实际上就是这个:
| deleteNil l == Nil = deleteNil r
因为它应该是
| deleteNil l == Nil && deleteNil r /= Nil = deleteNil r
因为你想要返回一个不包含Nil
s。
此外,您可以为Eq
类型类提供实例:
instance Eq (Tree a) where
Nil == Nil = True
Br l1 r1 == Br l2 r2 = l1 == l2 && r1 == r2
_ == _ = False