我正在尝试为图形编写类型类。基本上,类型类看起来像:
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 { ... }
但是这要求g
中的class Graph g
有*
而不是* -> *
,这样我就无法显示n
取决于g
。
那我该怎么办呢?感谢。
答案 0 :(得分:5)
可以在向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
如果你考虑一下,这是有道理的:图形需要一个顶点的概念。