【问题标题】:Describing a typeclass for general graphs in Haskell在 Haskell 中为一般图描述类型类
【发布时间】:2016-07-19 15:29:41
【问题描述】:

我正在尝试为图形编写一个类型类。基本上,类型类看起来像:

class Graph g where
  adjacentNodes :: g n -> n -> [n]

其中我使用n来表示节点的类型。

然后我有以下Graph 定义如下:

data FiniteGraph n = FiniteGraph { runFiniteGraph :: Array n [n] }

其中Array取自标准容器Data.Array,其结构是表示一个有限图,以将每个节点映射到其相邻节点的方式。

问题来了,当我尝试将FiniteGraph 设为Graph 的实例时。

instance Graph FiniteGraph where
  adjacentNodes g n = (runFiniteGraph g) ! n

不幸的是,这不起作用,因为! 运算符需要约束Ix n,但我找不到在哪里声明它。

我希望实例声明类似于:

instance (Ix n) => Graph (FiniteGraph n) where { ... }

但这要求class Graph g 中的g 具有* 而不是* -> *,这样我就无法证明n 依赖于g

那我能用它做什么呢?谢谢。

【问题讨论】:

    标签: haskell graph polymorphism typeclass type-theory


    【解决方案1】:

    Graph 类中添加第二个参数后即可完成。

    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE FunctionalDependencies #-}
    {-# LANGUAGE FlexibleInstances #-}
    import Data.Array
    
    class Graph g n | n -> g where
      adjacentNodes :: g n -> n -> [n]
    
    data FiniteGraph n = FiniteGraph { runFiniteGraph :: Array n [n] }
    
    instance Ix n => Graph FiniteGraph n where
      adjacentNodes g n = (runFiniteGraph g) ! n
    

    如果您考虑一下,这很有道理:图形需要顶点的概念。

    【讨论】:

    • 如何转换函数依赖:g -> n?这样你就可以拥有具有相同节点类型(例如Int)的不同图(例如边列表、邻接矩阵)。
    • 移除函数依赖就足够了。
    猜你喜欢
    • 2017-08-13
    • 1970-01-01
    • 2011-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多