#haskell #graph
#haskell #График
Вопрос:
Я пытаюсь разобраться с Haskell, и я нашел несколько семинаров, в которых предлагается создать структуру данных графа. Я последовал примеру и создал двоичное дерево, используя map, что было намного проще. У меня есть следующие типы данных
type Graph a = [(Node a, Edges)]
type Edges = [NodeID]
type NodeID = Int
data Node a = Node
{ getNodeID :: NodeID,
getNodeVal :: a
}
deriving (Show, Eq)
и пример узла будет следующим
nodeA = Node 0 'A'
и пример графа, связанного в обоих направлениях, будет
graphA = [(nodeA, [1]), nodeB, [0]]
Теперь, чтобы выполнить какую-либо операцию вставки или удаления, мне сначала нужно было бы выяснить, каков максимальный NodeID на данный момент. Итак, я пытаюсь написать maxNodeID следующим образом
maxNodeID :: Graph a -> Maybe NodeID
maxNodeID [] = Nothing --base case
Но мне очень сложно придумать следующий вариант для этой функции.
Мое определение типа для функции insertNode выглядит следующим образом
insertNode :: a -> Graph a -> Graph a
-- This is my idea for a base case but I get a parse error at 0
insertNode v [] = [a, []] where a = Node {0, v}
Любая помощь в этом и создании функции insertNode была бы очень признательна, поскольку это действительно помогло бы мне встать на правильный путь.
Ответ №1:
Вместо того, чтобы создавать свою собственную, я бы использовал maximumBy :: Foldable t => (a -> a -> Ordering) -> t a -> a
функцию из Data.List .
maxNodeID :: Graph a -> Maybe NodeID
maxNodeID [] = Nothing --base case
maxNodeID xs = Just $ maximumBy (a b -> compare (getID a) (getID b)) xs
where getID = getNodeID . fst
Для вашей insertNode
функции вам нужно
insertNode v [] = [(a, [])] where a = Node 0 v
-- or --
insertNode v [] = [(a, [])] where a = Node {getNodeID = 0, getNodeVal= v}
Отредактировано для добавления:
Если вам еще не знакомы классы типов, вы можете прочитать тип maximumBy
specialized для списков как :: (a -> a -> Ordering) -> [a] -> a
.
Комментарии:
1. не могли бы вы пояснить, зачем использовать () вместо {}, хотя типы данных узла — {} , который выглядит как словарь ds (если думать на других языках), а не кортеж. Также я не видел Just или maximumBy раньше, чем прочитаю об этом. Но будет ли это достижимо с помощью foldr?
2. Извините, я торопился. Проверьте синтаксис Haskell для создания записей. (1 из 2)
3.
Just
это другой конструктор для Maybe. Если есть одна ветвь, тоNothing
должна быть и другаяJust (...)
. Да, можно написать, используя justfoldr
(могут быть все функции класса Foldable), но зачем, когда для вас уже есть отличная библиотечная функция?4. Я должен был уточнить с самого начала, понимание foldr и map для меня важнее, поскольку они кажутся строительными блоками. Мне нужно попрактиковаться в понимании основ, прежде чем я начну использовать встроенные функции libtaty. Следовательно, это упражнение по созданию структур данных, которые я мог бы легко реализовать на нефункциональных языках. Я пытаюсь думать о тех же проблемах, но более функционально.