Получить значения из типа данных - PullRequest
0 голосов
/ 03 июля 2019

Я пытаюсь реализовать граф объектов в Haskell, и у меня есть простой тип Node, который содержит идентификатор и список подключенных узлов.

data Node = Node Integer [Node] deriving (Show)

Моя проблема связана с этими типами, в частности с получением значений. Например, я хочу посмотреть на значение Integer внутри узла; возможно найти предмет с id = 0

nodes = [Node 0 []]
[n | n <- nodes, fst n == 0]

• Couldn't match expected type ‘(Integer, b0)’
                  with actual type ‘Node’
    • In the first argument of ‘fst’, namely ‘n’
      In the first argument of ‘(==)’, namely ‘fst n’
      In the expression: fst n == 0

Хорошо, поэтому я не могу использовать fst. Я тоже не могу использовать !!. Я могу написать функцию, которая вытягивает значение наподобие

nodeId :: Node -> Integer
nodeId (Node i _) = i

и теперь [n | n <- nodes, nodeId n == 0] будет работать.

Есть ли другой способ получить значения из типов данных, подобных этому? Это правильный шаблон?

Ответы [ 2 ]

8 голосов
/ 03 июля 2019

Единственный способ получить значения из конструктора данных - это сопоставить его с шаблоном. Если вы хотите, вы можете определить функцию, которая делает это, как вы сделали с nodeId, или вы можете просто выполнить сопоставление с образцом в строке. Например, вы можете написать

[n | n@(Node id _) <- nodes, id == 0]

Или, так как понимание списка пропускает значения, для которых шаблон не работает, более короткая версия будет

[n | n@(Node 0 _) <- nodes]
5 голосов
/ 03 июля 2019

Вы также можете использовать синтаксис записи для генерации функций доступа для полей:

data Node = Node { nodeId :: Integer,
                   children :: [Node]
                 } deriving (Show)

[n | n <- nodes, nodeId n == 0]

Хотя это имеет обратную сторону, что это загрязняет;он создает функции на основе имен полей.Это означает, что вы не можете иметь две записи с полями с одинаковыми именами.Вы также не можете иметь свои собственные функции с тем же именем, что и имя поля записи.

Однако, как упоминает @KA Buhr, GHC имеет расширение , которое помогает облегчить хотя бы одну из этих проблем.

...