将数据类型变成Haskell中Show的实例

14

我需要将以下数据类型作为 Show 的实例:

data Tree a b = Branch b (Tree a b) (Tree a b) | Leaf a 

我是一个相对新手,但首先,我解释了这个声明:

"我们创建了一个名为Tree的新类型,它使用类型a和b进行参数化。一棵树可以是两种东西之一:Branch,它保存了类型为b的数据项以及另外两棵树,或者是Leaf,它保存了类型为a的数据项。"

现在,我需要制作一种漂亮的“显示”方式(嵌套分支等),而不使用deriving。到目前为止,我只在模块Main中编写函数,并在解释器窗口中加载/播放它们,因此我以前实际上并没有使用构造函数等来做事情。尽管如此,我认为我可以从在我的文件中声明树数据类型开始,就像问题开头所示,然后从那里开始。

当我尝试“Show”时,没有太大的成功,我想也许我需要先定义一小部分树以及如何“Show”它,然后再尝试整个树:

data Leaf a = Leaf a

instance Show (Leaf a) where
show (Leaf a) = ??? 

我在 ??? 处尝试了很多方法,比如 "a",只有 a 自己,putStrLn 等等,但是当我使用类似于以下方式时,都没有打印出 a 的值。

>show (Leaf 3)

实际上,我在很多情况下都遇到过这种情况,这可能意味着我没有正确地定位事物:

Ambiguous occurrence `show'
    It could refer to either `Main.show', defined at a2.hs:125:1
                          or `Prelude.show',
                             imported from `Prelude' at a2.hs:2:8-11
                             (and originally defined in `GHC.Show')

我尝试通过调用 "Main.show" 来解决这个问题,但显然不起作用。

我想我的问题是,我该去哪里解决这个问题呢...或者只是简单地说,"我如何修复 Leaf 的“Show”实用程序,以便我可以找出如何扩展它?"(假设我必须先定义它...)

4个回答

24

你必须像这样开始:

data Tree a b = Branch b (Tree a b) (Tree a b) | Leaf a

instance (Show a, Show b) => Show (Tree a b) where
    show (Leaf x) = show x
    show (Branch p l r) = ???

要显示一个 Tree a b,你首先需要能够显示 ab。这就是 (Show a, Show b) => 这部分所做的事情,它指定了您的实例需要的前提条件。


9
这里有一个小提示:通过编写
 instance Show (Leaf a) where
 show (Leaf a) = ???

实际上,您所做的是定义了一个空的 Show 实例,然后是一个顶层的 show 函数。这就是为什么会出现 "ambiguous show" 错误的原因;您定义了一个新的 show 函数,其名称与现有函数冲突。

您想要表达的意思是:

 instance Show (Leaf a) where
   show (Leaf a) = ???

请注意第二行现在已经缩进了。这意味着您正在重新定义现有的 show 方法,正如您预期的那样。

8
最简单的答案是自动派生一个Show实例:
data Tree a b = Branch b (Tree a b) (Tree a b) | Leaf a deriving Show

但是假设这不会给你想要的格式输出。如果你想要定义自己的Show示例,你需要执行以下操作:

instance (Show a, Show b) => Show (Tree a b) where
    show (Leaf a) = "Leaf " ++ (show a)
    show (Branch b l r) = "Branch " ++ (show b) ++ " { " ++ l ++ ", " ++ r " }"

如果你读到了第一行,可能的理解是,“假设ab都是Show类型类的实例,那么Tree a b也是Show类型类的实例...”。此外,缩进很重要。它可能会在你复制粘贴的代码片段中混乱,但你必须将show函数定义缩进到instance声明下面。

2

您的数据类型非常适合使用 deriving Show

data Tree a b = Branch b (Tree a b) (Tree a b) | Leaf a deriving Show

这将自动生成相应的Show实例。

如果您想手动创建Show实例,以下是思考过程。

首先,基本骨架:

instance Show (Tree a b) where
   -- show :: Tree a b -> String
   show (Branch b ltree rtree) = {- some string -}
   show (Leaf a) = {- some string -}

现在我们知道需要以字符串形式显示类型为ab的值。当然,这意味着我们需要能够直接调用它们的show方法,因此ab必须具有Show实例。以下是如何完成的:
instance (Show a, Show b) => Show (Tree a b) where
   -- show :: Tree a b -> String
   show (Branch b ltree rtree) = {- some string -}
   show (Leaf a) = {- some string -}

然后只需用适当的字符串填充空白,例如:
instance (Show a, Show b) => Show (Tree a b) where
   -- show :: Tree a b -> String
   show (Branch b ltree rtree) = "(( " ++ show ltree ++ " ) <-- ( " ++ b ++ " ) --> ( " ++ show rtree ++ " ))"
   show (Leaf a) = "L " ++ show a

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接