代码之家  ›  专栏  ›  技术社区  ›  Mantas Vidutis

具有集合的Haskell ORD实例

  •  1
  • Mantas Vidutis  · 技术社区  · 16 年前

    我有一些代码要用于将边缘附加到节点数据结构:

    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 回复  |  直到 16 年前
        1
  •  6
  •   C. A. McCann Ravikant Cherukuri    16 年前

    在GHCi:

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

    所以,是的,它确实期望 Ord . 至于什么 奥德 意思是,这是 类型类 对于 有序值 . 在这种情况下是必须的,因为 Data.Set 使用搜索树,因此需要能够比较值,以查看哪个值更大或是否相等。

    几乎所有的标准内置数据类型都是 奥德 以及列表、元组等, Maybe 等是 奥德 当其类型参数为时。当然,最显著的例外是函数,在函数中不能定义合理的排序(甚至相等)概念。

    在许多情况下,可以使用 deriving 声明后条款:

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

    对于参数化类型,自动派生取决于类型参数也是一个实例,列表、元组等的情况也是如此。

    此外 奥德 ,一些重要的类型类是 Eq (相等比较,但不小于/大于) Enum (可以枚举值的类型,例如计数 Integer s) Read / Show (使用字符串进行简单的序列化/反序列化)。要了解有关类型类的更多信息,请尝试 this chapter in Real World Haskell 或者,为了更全面地了解 a Wikipedia article .

        2
  •  4
  •   Geoff Reedy    16 年前

    haskell集基于搜索树。为了将元素放入搜索树中,必须对元素进行排序。通过将ORD添加到数据声明中,您可以像派生显示一样派生ORD,即:

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

    通过data.set.insert的签名可以看到ORD的要求。

    (Ord a) => a -> Set a -> Set a
    

    部分 (Ord a) => 建立一个约束,使typeclass存在一个实例 Ord 对于 a . 这个 section on type classes haskell tutorial 给出了更详细的解释。