Kir*_*rst 0 syntax haskell algebraic-data-types
我正在尝试在Haskell中实现对象图,并且我有一个简单的Node类型,其中包含一个标识符和一个已连接节点的列表。
data Node = Node Integer [Node] deriving (Show)
Run Code Online (Sandbox Code Playgroud)
我的问题是对这些类型进行操作-特别是检索值。例如,我想查看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
Run Code Online (Sandbox Code Playgroud)
好的,所以我不能使用fst。我不能使用!!。我可以编写一个函数来提取值,例如
nodeId :: Node -> Integer
nodeId (Node i _) = i
Run Code Online (Sandbox Code Playgroud)
现在[n | n <- nodes, nodeId n == 0]可以工作了。
还有另一种方法可以从这样的数据类型获取值吗?这是正确的模式吗?
从数据构造函数中获取值的唯一方法确实是对其进行模式匹配。如果需要,您可以定义一个执行该功能的函数,就像使用所做的那样nodeId,也可以直接内联进行模式匹配。例如,你可以写
[n | n@(Node id _) <- nodes, id == 0]
Run Code Online (Sandbox Code Playgroud)
或者,由于列表推导会跳过模式失败的值,因此较短的版本是
[n | n@(Node 0 _) <- nodes]
Run Code Online (Sandbox Code Playgroud)
您还可以使用记录语法为字段生成访问器函数:
data Node = Node { nodeId :: Integer,
children :: [Node]
} deriving (Show)
[n | n <- nodes, nodeId n == 0]
Run Code Online (Sandbox Code Playgroud)
尽管这有污染的缺点;它根据字段名称创建函数。这意味着您不能有两个记录具有相同名称的字段。您也不能拥有与记录的字段名称相同名称的函数。
正如@KA Buhr提到的那样,GHC确实具有扩展名,可以帮助缓解至少其中一个问题。