带有Set的Haskell Ord实例

时间:2010-06-17 20:42:26

标签: haskell set

我有一些代码可以用来将边缘附加到Node数据结构:

import Data.Set (Set)
import qualified Data.Set as Set

data Node = Vertex String (Set Node)
    deriving Show

addEdge :: Node -> Node -> Node
addEdge (Vertex name neighbors) destination
    | Set.null neighbors    = Vertex name (Set.singleton destination)
    | otherwise             = Vertex name (Set.insert destination neighbors)

然而,当我尝试编译时,我收到此错误:

No instance for (Ord Node)
      arising from a use of `Set.insert'

据我所知,Set.insert只需要一个值和一个插入它的集合。这个奥德是什么?

2 个答案:

答案 0 :(得分:6)

在GHCi中:

> import Data.Set
> :t insert
insert :: (Ord a) => a -> Set a -> Set a

是的,它确实期待Ord。至于Ord的含义,对于有序值,它是类型类。在这种情况下需要它,因为Data.Set使用搜索树,因此需要能够比较值以查看哪个更大或者它们是否相等。

几乎所有标准内置数据类型都是Ord的实例,以及列表,元组,Maybe等等,当它们的类型为Ord的实例时参数是。当然,最值得注意的例外是函数,其中没有明确的排序概念(甚至是相等)。

在许多情况下,您可以在声明后使用deriving子句自动为您自己的数据类型创建类型类的实例:

data Foo a = Foo a a Int deriving (Eq, Ord, Show, Read)

对于参数化类型,自动派生取决于类型参数也是一个实例,就像列表,元组等一样。

Ord之外,一些重要的类型类是Eq(相等比较,但不小于/大于),Enum(您可以枚举值的类型,例如count {{ 1}} s)和Integer / Read(使用字符串进行简单的序列化/反序列化)。要了解有关类型类的详情,请尝试this chapter in Real World Haskell,或者,对于更一般的概述,请a Wikipedia article

答案 1 :(得分:4)

Haskell集基于搜索树。为了将元素放在搜索树中,必须给出元素的排序。你可以通过将它添加到数据声明中来推导出Ord,就像你将它显示出来一样,即:

data Node = Vertex String (Set Node)
   deriving (Show, Eq, Ord)

您可以通过Data.Set.insert

的签名来查看Ord的要求
(Ord a) => a -> Set a -> Set a

部分(Ord a) =>建立了一个约束,即Ord的类型类a的实例。 section on type classes中的haskell tutorial给出了更全面的解释。