Haskell派生显示实例

Joe*_*Joe 5 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 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
Run Code Online (Sandbox Code Playgroud)

如果我在GHCi中执行以下语句:

> RedBlackTree.insert ('b') (RedBlackTree.T R E ('a') E)
Run Code Online (Sandbox Code Playgroud)

以下错误消息告诉我没有show的实例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
Run Code Online (Sandbox Code Playgroud)

我知道树正在工作,因为通过调用先前执行的语句member 'b' ...在哪里...,返回的值是True.我一直在阅读关于这个问题的其他SO帖子,但是为他们找到的解决方案(例如:Haskell:自定义类型的导出显示)不起作用.

例如,添加:

instance Show Set where:
    show (Set Char) = show Char
Run Code Online (Sandbox Code Playgroud)

我尝试加载时收到以下错误消息:l:

:l red-black-tree.hs [1/1]编译RedBlackTree(red-black-tree.hs,解释)

red-black-tree.hs:54:11: Not in scope: data constructor `Set'

red-black-tree.hs:54:15: Not in scope: data constructor `Char'

red-black-tree.hs:54:28: Not in scope: data constructor `Char'
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)

我认为我正在尝试做的事情有一些问题,但我似乎无法从可用的文档中找到它.

Jan*_*sen 5

要将值转换为字符串,Haskell使用所谓的类型类.简化后,类型类只提供根据其参数类型而行为不同的函数.这种方法与面向对象编程语言中已知的方法重载非常相似.type类Show提供了一个函数show,用于将某种类型的值转换为字符串.例如,表达式show 1产生字符串"1".如果有一个函数show将某种类型的值转换为字符串,我们就说Show这种类型有一个类型类的实例.换句话说,有一个Show整数类型类的实例.

show在ghci中计算表达式时也会使用此函数.因此,它告诉您没有实例(Show (Set Char)),换句话说,它不知道如何将类型的值Set Char转换为字符串.对于自定义类型,如你的类型Set,RBTColor您必须提供类型的类的实例Show,以在控制台上显示论文类型的值.要定义类型的类的实例Show的类型Color,你可以使用下面的定义.

instance Show Color where:
  show R = "Red"
  show B = "Black"
Run Code Online (Sandbox Code Playgroud)

也就是说,如果你写入Rghci,它会打印出来Red.对于简单的Haskell数据类型,有一个Show类型类的规范定义.例如,Showfor 的规范定义Color如下.

instance Show Color where:
  show R = "R"
  show B = "B"
Run Code Online (Sandbox Code Playgroud)

为了减轻用户定义这样的实例,Haskell提供了一种所谓的"派生机制".也就是说,如果你写

  deriving (Show)
Run Code Online (Sandbox Code Playgroud)

在定义数据类型之后,编译器将为Show您的数据类型生成类型类的规范实例.

如果数据类型使用其他数据类型,则派生Show前者的Show实例将需要后者的实例.例如,请考虑以下数据类型.

data RBT e = E | T Color (RBT e) e (RBT e)
Run Code Online (Sandbox Code Playgroud)

数据类型在其定义中RBT使用类型Color.构造函数的规范Show实例T将以"T"开头,然后显示type的值Color.因此,推导Show例如RBT需要实例ShowColor.


Lev*_*son 1

您没有使用任何花哨的扩展,因此您应该能够deriving使用Show.

为了使其自动派生Show数据类型的实例,类型定义中使用的所有类型也必须具有Show实例。只需添加到所有定义的deriving (Show)末尾即可。您可能只想养成添加到所有类型的习惯,因为您几乎总是希望类型具有结构相等性测试和可显示性。dataderiving (Eq, Show)data

另外,您不能为类型别名创建任何类型的类实例,而只能为类型创建。该关键字type定义类型别名,而不是新类型。如果您Show为您的类型创建一个实例RBT a,它将自动用于您声明为 a 的任何内容Set a,因为Set a它只是 的别名RBT a