с предварительным заказом для обхода IntTree

#haskell #preorder

#haskell #предварительный заказ

Вопрос:

Я пытаюсь создать функцию предварительного заказа для обхода IntTree.

Класс дерева выглядит следующим образом

 data IntTree = Empty | Branch IntTree Int IntTree deriving (Show, Eq)
  

У меня есть два вопроса
1. Я получаю ошибки, как показано ниже.

 E:HaskellUebungsblatt_2_Aufgabe_2_a.hs:7:14: error:
    * Expected kind `* -> Constraint', but `IntTree' has kind `*'
    * In the type signature: preorder :: (IntTree c) => c -> [a]
  |
7 | preorder :: (IntTree c) => c->[a]

  |              ^^^^^^^^^
[Finished in 0.5s]
  

Я не понимаю, почему. Они произошли в этой следующей строке

 preorder :: (IntTree c) => c->[a]
  
  1. Я думаю, что следующая строка неверна. Я думаю, мне нужно написать другие выражения вместо » l: предварительный заказ a: предварительный заказ r: [] «

 preorder Branch a l r = l : preorder a : preorder r:[]
  

Заранее благодарю вас за помощь!!

 main :: IO ()    -- This says that main is an IO action.
main = return () -- This tells main to do nothing

data IntTree = Empty | Branch IntTree Int IntTree deriving (Show, Eq)


preorder :: (IntTree c) => c->[a]
preorder Empty = []
preorder Branch Empty x Empty = [x]
preorder Branch a l r = l : preorder a : preorder r:[]
  

Ответ №1:

Для вопроса 1:

 preorder :: (IntTree c) => c->[a]
  

Вы путаете классы и типы данных. IntTree был объявлен с помощью data , поэтому это не класс типов, а обычный тип данных, такой как Bool или Int . Он используется таким же образом:

 preorder :: IntTree -> [a]
  

Во-вторых, вы не возвращаете список какого-либо типа a (строчные буквы — это переменные типа), вы возвращаете конкретно список Int s, потому что это то, что содержит дерево. Итак, вы должны так сказать:

 preorder :: IntTree -> [Int]
  

Ответ №2:

Для вопроса 1: подпись

 preorder :: (IntTree c) => c->[a]
  

неверно: IntTree это не класс типов, это обычный тип, поэтому мы можем использовать его как есть.

 preorder :: IntTree -> [Int]
  

Конечный тип должен быть Int , поскольку мы создаем список целых чисел, а не список [a] для любого a .

Для вопроса 2: : добавляет элемент к списку, он имеет тип

 (:) :: a -> [a] -> [a]
  

Следовательно, он не объединяет два списка. Для этого используйте вместо

 (  ) :: [a] -> [a] -> [a]
  

как в

 preorder (Branch a l r) = l : preorder a    preorder r
  

(Нет необходимости использовать [] в конце)

Комментарии:

1. Черт возьми, вы добавили раздел с вопросом 1. Мне понравился наш однозначный двойной ответ.

2. @luqui Я понял, что был вопрос 1 после того, как я ответил на вопрос 2, поэтому я сначала пометил ответ как только для Q2, и я начал редактировать, чтобы завершить ответ. Да, ответы «split» выглядели лучше, в некотором эстетическом смысле 🙂

3. Только что я исправил это после ваших подсказок. Но в следующей строке все еще есть одна ошибка: preorder Empty = [] . Ошибка в E:HaskellUebungsblatt_2_Aufgabe_2_a.hs:8:1: error: Equations for `preorder' have different numbers of arguments E:HaskellUebungsblatt_2_Aufgabe_2_a.hs:8:1-19 E:HaskellUebungsblatt_2_Aufgabe_2_a.hs:9:1-35 | 8 | preorder Empty = [] | ^^^^^^^^^^^^^^^^^^^^... [Finished in 0.5s] @chi @luqui

4. @LeonhardFelix Вам нужно больше круглых скобок: preorder Branch a l r = ... это функция, которая принимает 4 аргумента, в то время как то, что вы хотите, preorder (Branch a l r) = ... . Я соответствующим образом отредактировал свой ответ.

5. @chi большое спасибо