Haskell派生Show实例
我在玩一棵红黑的树:Haskell派生Show实例,haskell,show,deriving,Haskell,Show,Deriving,我在玩一棵红黑的树: -- Taken from Okasaki 1999 module RedBlackTree where --node coloring data --a node is R (red) or B (black) data Color = R | B --tree constructor --a RBT can be E (empty) or be T (a non empty tree) data RBT e = E | T Color (RBT e) e (RBT
-- Taken from Okasaki 1999
module RedBlackTree where
--node coloring data
--a node is R (red) or B (black)
data Color = R | B
--tree constructor
--a RBT can be E (empty) or be T (a non empty tree)
data RBT e = E | T Color (RBT e) e (RBT e)
--set operations on tree
type Set a = RBT a
--define an empty set
empty :: Set e
empty = E
--define a member of a set
--Sees if an item of type e is
--in a set if type e elements
member :: (Ord e) => e -> Set e -> Bool
member x E = False
member x (T _ a y b) | x < y = member x a -- if less, go left
| x == y = True
| x > y = member x b -- if more, go right
--tree operations
--Insert an element
insert :: (Ord e) => e -> Set e -> Set e
insert x s = makeBlack (ins s)
where ins E = T R E x E --basically the typical BST insert
ins (T color a y b) | x < y = balance color (ins a) y b
| x == y = T color a y b
| x > y = balance color a y (ins b)
makeBlack (T _ a y b) = T B a y b --inserts a black node
-- balance operations
--case 1:
balance B (T R (T R a x b) y c) z d = T R (T B a x b) y (T B c z d)
--case 2:
balance B (T R a x (T R b y c)) z d = T R (T B a x b) y (T B c z d)
--case 3:
balance B a x (T R (T R b y c) z d) = T R (T B a x b) y (T B c z d)
--case 4:
balance B a x (T R b y (T R c z d)) = T R (T B a x b) y (T B c z d)
--generic balancing operation
balance color a x b = T color a x b
下面的错误消息告诉我没有显示Set Char
的实例:
<interactive>:116:1:
No instance for (Show (Set Char)) arising from a use of `print'
Possible fix: add an instance declaration for (Show (Set Char))
In a stmt of an interactive GHCi command: print it
尝试使用加载时,我收到以下错误消息:l
:
:l红色-黑色-树.hs
[1/1]编译RedBlackTree(red-black-tree.hs,已解释)
我认为我试图做的事情存在一些问题,但我似乎无法从可用的文档中找到答案。您没有任何花哨的扩展正在使用,因此您应该能够使用内置的
派生
机制来显示
为了自动为数据类型派生Show
实例,类型定义中使用的所有类型也必须具有Show
实例。只需在所有数据的末尾添加派生(显示)
。您可能希望养成向所有数据
类型中添加派生(Eq,Show)
的习惯,因为您几乎总是希望类型的结构相等性测试和可显示性
此外,不能为类型别名创建任何排序的类实例,只能为类型创建。关键字type
定义类型别名,而不是新类型。如果为您的RBT a
类型创建Show
实例,它将自动用于您声明为Set a
的任何内容,因为Set a
只是RBT a
的别名,您的实例代码已被破坏:
instance Show Set where
show (Set Char) = show Char
编译器抱怨Set
不是一个数据构造函数,它不是-它是一个类型同义词名称。因此,您在模式中错误地使用了Set
。您可以在那里使用数据构造函数-对于RBT
,数据构造函数是T
和E
您的实例声明类型不正确:Set
是RBT
的同义词,RBT
有一个类型参数,即它是从一个类型到另一个类型的函数,类型签名为*->*
。但是Show
实例需要一个没有参数的类型,它是一个类型而不是一个类型构造函数,类型是*
,而不是您提供的*->*
。因此,您应该通过提供instance Show(RBT Char)
或instance(Show a)=>RBT a来解决这个问题
您可能想要写的是“通过显示一组字符中的字符来显示一组字符”
因此,要修复您的实例:
instance Show (RBT Char) where
show a = "something"
但它没有显示任何有用的东西。您需要对RBT的构造函数进行模式匹配以完成工作:
instance Show (RBT Char) where
show E = "something"
show (T a b c d) = "something else"
但是对于您的任务来说,只需为RBT a
和Color
使用派生的Show
实例将值转换为字符串就更简单了,Haskell使用了所谓的类型类。简化的类型类只提供根据参数类型不同而表现不同的函数。这种方法与面向对象编程语言中已知的方法重载非常相似。type类Show
提供了一个名为Show
的函数,该函数将某种类型的值转换为字符串。例如,表达式show 1
生成字符串“1”
。如果有一个函数show
将某个类型的值转换为字符串,我们就说这个类型有一个type类show
的实例。换句话说,有一个整数类型类Show
的实例
在ghci中计算表达式时,也会使用此show
函数。因此,它告诉您没有实例(Show(Set Char))
,换句话说,它不知道如何将Set Char
类型的值转换为字符串。对于自定义类型,如您的类型Set
、RBT
和Color
,您必须提供类型类Show
的实例,以便在控制台上显示这些类型的值。要为类型Color
定义类型类Show
的实例,可以使用以下定义
instance Show Color where:
show R = "Red"
show B = "Black"
也就是说,如果将R
写入ghci,它将打印红色
。对于简单的Haskell数据类型,有一个Show
type类的规范定义。例如,Color
的Show
的规范定义如下
instance Show Color where:
show R = "R"
show B = "B"
为了避免用户定义这样的实例,Haskell提供了一种所谓的“派生机制”。也就是说,如果你写
deriving (Show)
定义数据类型后,编译器将为您的数据类型生成Show
type类的规范实例
data RBT e = E | T Color (RBT e) e (RBT e)
如果一个数据类型使用另一个数据类型,则派生前者的Show
实例将需要后者的Show
实例。例如,考虑下面的数据类型。
data RBT e = E | T Color (RBT e) e (RBT e)
数据类型RBT
在其定义中使用类型Color
。T
构造函数的规范Show
实例将以“T”开头,然后显示类型Color
的值。因此,为RBT
导出Show
实例需要为Color
导出Show
实例,只需使用data Tree a=。。。派生(显示)
将派生(显示)
附加到数据RBT的末尾…
给出了以下错误消息:没有因数据类型声明的“派生”子句而产生的(显示颜色)实例
只需将派生(显示)
添加到数据颜色=R|B
deriving (Show)
data RBT e = E | T Color (RBT e) e (RBT e)