Создание типа данных экземпляра 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
a
s и b
s. Вот что такое (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