Создание типа данных экземпляра Show в Haskell

мне нужно сделать следующий тип данных экземпляром Show:

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

Я довольно новичок в этом, но для начала я интерпретировал это заявление как

" мы создали новый тип дерева, который параметризован типами a и b. Дерево может быть одним из двух: ветвью, которая содержит фрагмент данных типа b, плюс еще два дерева, или листом, который содержит элемент данных типа a."

теперь мне нужно сделать способ" показать " его красиво (вложенный филиалы и т. д.), без использования deriving. До сих пор я только писал функции в главном модуле и загружал/играл с ними в окне интерпретатора, поэтому я на самом деле не делал ничего с конструкторами и т. д. Тем не менее, я решил, что могу просто начать с объявления типа данных дерева в моем файле, как показано в начале вопроса, и перейти оттуда.

поскольку я возился с " шоу " без особого успеха, я подумал, что, возможно, мне нужно определить небольшой компонент дерева и как" показать " его сначала, прежде чем пытаться работать со всем деревом:

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.шоу," что, конечно, не работает.

Я думаю, вопрос в том, куда я иду со всем этим...или, может быть, просто: "как я могу исправить утилиту" показать лист", чтобы я мог понять, как ее расширить?- (предполагая, что сначала мне придется дать ему определение...)

4 ответов


вы должны начать так:

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 a Tree a b вы должны сначала быть в состоянии show as и bs. Вот что такое (Show a, Show b) => часть делает, она определяет предварительные условия, необходимые для работы вашего экземпляра.


вот небольшой намек: написав

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

что ты на самом деле неужели было определить пустой Show экземпляр, за которым следует верхний уровень . Вот почему вы получаете " неоднозначный show" ошибка; вы определили новый show функция, имя которой противоречит существующему.

что ты означает сказать

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

обратите внимание, как теперь отступ второй строки. Это значит, что ты ... переопределение существующего show способ, как вы, вероятно, предполагалось.


самый простой ответ - автоматически получить 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 typeclass, Tree a b тоже экземпляр Show typeclass..."

кстати, отступ важных. Возможно, он был искорежен в фрагменте, который вы вставили, но вы должны отступить show определения функций под instance декларации.


ваши данные-тип-идеальный кандидат для 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 -}

теперь мы знаем, что нам понадобится какой-нибудь способ показать значения типа a и b как струны. Конечно, это означает, что мы должны иметь возможность позвонить 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