13

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

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

我对此很陌生,但首先,我将此声明解释为

“我们创建了一个新类型,称为 Tree,它使用类型 a 和 b 进行参数化。一棵树可以是以下两种情况之一:一个持有 b 类型数据的分支,再加上两棵树,或者一个持有a 类型的数据项。”

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

当我搞砸“显示”但没有取得多大成功时,我想也许我需要定义树的一个小组件以及如何首先“显示”它,然后再尝试使用整个树:

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

4 回答 4

22

你必须这样开始:

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) = ???

为了showa Tree a b,您必须首先能够show as和bs。这就是该(Show a, Show b) =>部分的作用,它指定了您的实例工作所需的先决条件。

于 2012-09-21T19:43:37.520 回答
8

这是一个小提示:通过写作

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

实际上所做的是定义一个 Show实例,然后是一个顶级show函数。这就是为什么你会得到“模棱两可show”的错误;您定义了一个新show函数,其名称与现有函数冲突。

你想说的

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

注意第二行现在是如何缩进的。这意味着您正在重新定义现有show方法,正如您可能想要的那样。

于 2012-09-27T08:44:50.977 回答
7

最简单的答案是自动派生一个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 " }"

您可能会读到第一行的方式是,“给定a并且b都是Show类型类Tree a b的实例,也是类型类的实例Show......”

顺便说一句,缩进很重要。它可能在您粘贴的代码段中被破坏了,但您必须在声明show下缩进函数定义。instance

于 2012-09-21T19:47:10.290 回答
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直接调用它们,因此a必须b有 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
于 2012-09-21T19:42:28.323 回答