我想模拟一些常规结构的大树(或森林) - 树可以分解为小树(不规则部分)和(即)大型参数列表,每个节点与每个节点组成一个节点大树。
所以,我想要一个数据结构,其中树中的每个节点代表许多节点。真正的节点是类型(节点,参数)。
对于在这种树上工作的算法,该类型的param不会消磨。它们只是占位符。但是一些数据应该可以从普通参数或节点和参数的组合中提取,并且所有可能的参数都应该是可迭代的。所有这些类型的数据都是先验的,它们反映了该树的语义。
因此,实际的类型,语义和param的东西都取决于树的实现。
我在C ++中使用嵌套typedef为params类型建模,固定方法名称用于算法可用的所有类型的东西(这两个一起构成一个概念)和算法本身的模板。
即。如果我想将大树的每个节点与整数相关联,我会提供一个函数int data(const node& n, const param& p)
,其中param
可用作嵌套的typedef,算法可以得到所有可用参数的列表,并调用{ {1}}感兴趣的节点和每个参数
我有一些普通的数据类型,即树数据,就像这样
data
现在我要打包:
因此,可以编写一些使用这种打包类型和函数的函数,例如泛型方法。
如何实现?
对于类型系列,我来到了
data Tree = Node [Tree] | Leaf
class PackagedUp t where
type Value t
tree :: Tree t
values :: [Value t]
f :: Tree t -> Value t -> Int
现在变为Tree
,因为类型系列希望其成员类型依赖于类型类参数。
此外,与https://stackoverflow.com/a/16927632/1227578类型一样,需要处理注入的家庭。
有了这个,我可以
Tree t
现在怎么写这样的功能?即一个将生成树的根,所有值并生成instance PackagedUp MyTree where
type Value MyTree = (Int,Int)
tree = Leaf
values = [(0,0),(1,1)]
f t v = fst v
[Int]
的函数。
答案 0 :(得分:2)
首先,您的树类型应该像这样定义:
data Tree a = Node a [Tree a] | Leaf
上面的类型是多态的。就语义而言,它类似于我们在OO用语中称为泛型类型(在C#或Java中,我们可能会编写Tree<A>
)。 Tree a
的节点包含a
类型的值和子树列表。
接下来,我们来PackagedUp
。 Haskell中的类与同名的OO概念没什么关系;它们并不意味着将数据和行为打包在一起。事情实际上要简单得多:您需要做的就是为树类型定义适当的函数
getRoot :: Tree a -> Maybe a
getRoot Leaf = Nothing
getRoot (Node x _) = Just x
(返回Maybe a
是一种处理类型安全失败的简单方法。可以将Nothing
值视为null
的礼貌表兄,它不会因空引用异常而爆炸。 )
类型类擅长的一件事是表达数据结构算法接口,例如你提到的接口。最常见的类之一是Functor
,它为数据结构的映射提供了通用接口。
instance Functor Tree where
fmap f Leaf = Leaf
fmap f (Node x ts) = Node (f x) (fmap f ts)
fmap
具有以下多态类型:
fmap :: Functor f => (a -> b) -> f a -> f b
使用您的树,它专门用于
fmap :: (a -> b) -> Tree a -> Tree b
和列表(如fmap f ts
中所示)变为
fmap :: (a -> b) -> [a] -> [b]
最后,Data.Tree
模块提供的数据结构与您想要定义的内容非常相似。