将数据,类型和功能绑定在一起

时间:2014-04-26 18:17:56

标签: haskell typeclass type-families

我想模拟一些常规结构的大树(或森林) - 树可以分解为小树(不规则部分)和(即)大型参数列表,每个节点与每个节点组成一个节点大树。

所以,我想要一个数据结构,其中树中的每个节点代表许多节点。真正的节点是类型(节点,参数)。

对于在这种树上工作的算法,该类型的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]的函数。

1 个答案:

答案 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模块提供的数据结构与您想要定义的内容非常相似。