使数据类型成为Haskell中Show的实例

时间:2012-09-21 19:38:03

标签: haskell types tree instance show

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

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

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

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

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

当我用“Show”搞砸了没有太大的成功时,我想也许我需要在尝试使用整棵树之前定义树的一个小组件以及如何“显示”它:

data Leaf a = Leaf a

instance Show (Leaf a) where
show (Leaf 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 个答案:

答案 0 :(得分:21)

你必须这样开始:

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

为了show Tree a b,您必须首先能够show ab。这就是(Show a, Show b) =>部分的作用,它指定了实例运行所需的前提条件。

答案 1 :(得分:8)

这是一个小提示:写作

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

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

的意思

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

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

答案 2 :(得分:5)

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

您可以阅读第一行的方式是,#34;给定ab都是Show类型类的实例,Tree a b也是一个实例Show类型类..."

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

答案 3 :(得分: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