Algorithm Haskell NB:‘;边缘’;是一个非内射型族

Algorithm Haskell NB:‘;边缘’;是一个非内射型族,algorithm,haskell,typeclass,dijkstra,type-families,Algorithm,Haskell,Typeclass,Dijkstra,Type Families,我正试图用Haskell编写自己的图形库,以便在代码出现时使用。我试图使用一个图形类和一个使用Data.Map的具体实现。我正试图编写Dijkstra的算法,但我在类型族方面遇到了一些麻烦。我有以下typeclass和具体实现: {-# LANGUAGE TypeFamilies, AllowAmbiguousTypes, ScopedTypeVariables, TypeFamilyDependencies #-} class Graph g where type Node g ty

我正试图用Haskell编写自己的图形库,以便在代码出现时使用。我试图使用一个图形类和一个使用
Data.Map
的具体实现。我正试图编写Dijkstra的算法,但我在类型族方面遇到了一些麻烦。我有以下
typeclass
和具体实现:

{-# LANGUAGE TypeFamilies, AllowAmbiguousTypes, ScopedTypeVariables, TypeFamilyDependencies #-}

class Graph g where
  type Node g
  type Edge g
  nodeSet :: g -> S.Set (Node g)
  neighbours :: g -> (Node g) -> Maybe [(Edge g, Node g)]

data MapGraph e n = MapGraph {mGraph :: M.Map n [(e,n)]} deriving Show
instance (Num e,Ord e,Ord n) => Graph (MapGraph e n) where
  type Node (MapGraph e n) = n
  type Edge (MapGraph e n) = e
  nodeSet mapGraph = S.fromList $ M.keys $ mGraph mapGraph
  neighbours mapGraph node = M.lookup node (mGraph mapGraph)
为了在Dijkstra算法中表示未访问节点的
无穷
值,我创建了一个sum数据类型:

data MaxBoundedNum a = Inf | Num a deriving Show
我正在尝试使用算法的递归函数,该函数将包含图形、当前节点、目标节点、未访问集,以及节点的映射及其从源节点到源节点的长度。以下骨架函数似乎就是我想要的:

go :: (Graph g) =>
  g -> (Node g) -> (Node g) ->
  S.Set (Node g) ->
  M.Map (Node g) (MaxBoundedNum (Edge g)) ->
  Maybe (M.Map (Node g) (MaxBoundedNum (Edge g)))
go graph curr dest uset vals = do
  currNeighbours <- neighbours graph curr
  undefined
my
go
函数的下一部分需要查找距离
VAL
地图的当前距离

currDist <- M.lookup curr vals
但是,在
do
块中,我得到以下错误:

Could not deduce (Ord (Node g)) arising from a use of ‘M.lookup’
      from the context: Graph g
        bound by the type signature for:
                   go :: forall g.
                         Graph g =>
                         g
                         -> Node g
                         -> Node g
                         -> S.Set (Node g)
                         -> M.Map (Node g) (MaxBoundedNum (Edge g))
                         -> Maybe (M.Map (Node g) (MaxBoundedNum (Edge g)))
        at WithClass.hs:(96,1)-(100,49)
    • In a stmt of a 'do' block: currDist <- M.lookup curr vals
WithClass.hs:102:15: error:
    • Couldn't match type ‘Edge g’ with ‘Edge g1’
      Expected type: Maybe (MaxBoundedNum (Edge g1))
        Actual type: Maybe (MaxBoundedNum (Edge g))
      NB: ‘Edge’ is a non-injective type family
    • In a stmt of a 'do' block:
        currDist <- M.lookup curr vals :: Maybe (MaxBoundedNum (Edge g))
      In the expression:
        do currDist <- M.lookup curr vals :: Maybe (MaxBoundedNum (Edge g))
           currNeighbours <- neighbours graph curr
           undefined
      In an equation for ‘go’:
          go graph curr dest uset vals
            = do currDist <- M.lookup curr vals ::
                               Maybe (MaxBoundedNum (Edge g))
                 currNeighbours <- neighbours graph curr
                 undefined
    • Relevant bindings include
        vals :: M.Map (Node g) (MaxBoundedNum (Edge g))
          (bound at WithClass.hs:101:25)
        uset :: S.Set (Node g) (bound at WithClass.hs:101:20)
        dest :: Node g (bound at WithClass.hs:101:15)
        curr :: Node g (bound at WithClass.hs:101:10)
        graph :: g (bound at WithClass.hs:101:4)
        go :: g
              -> Node g
              -> Node g
              -> S.Set (Node g)
              -> M.Map (Node g) (MaxBoundedNum (Edge g))
              -> Maybe (M.Map (Node g) (MaxBoundedNum (Edge g)))
          (bound at WithClass.hs:101:1)
但这给了我一个错误:

Could not deduce (Ord (Node g)) arising from a use of ‘M.lookup’
      from the context: Graph g
        bound by the type signature for:
                   go :: forall g.
                         Graph g =>
                         g
                         -> Node g
                         -> Node g
                         -> S.Set (Node g)
                         -> M.Map (Node g) (MaxBoundedNum (Edge g))
                         -> Maybe (M.Map (Node g) (MaxBoundedNum (Edge g)))
        at WithClass.hs:(96,1)-(100,49)
    • In a stmt of a 'do' block: currDist <- M.lookup curr vals
WithClass.hs:102:15: error:
    • Couldn't match type ‘Edge g’ with ‘Edge g1’
      Expected type: Maybe (MaxBoundedNum (Edge g1))
        Actual type: Maybe (MaxBoundedNum (Edge g))
      NB: ‘Edge’ is a non-injective type family
    • In a stmt of a 'do' block:
        currDist <- M.lookup curr vals :: Maybe (MaxBoundedNum (Edge g))
      In the expression:
        do currDist <- M.lookup curr vals :: Maybe (MaxBoundedNum (Edge g))
           currNeighbours <- neighbours graph curr
           undefined
      In an equation for ‘go’:
          go graph curr dest uset vals
            = do currDist <- M.lookup curr vals ::
                               Maybe (MaxBoundedNum (Edge g))
                 currNeighbours <- neighbours graph curr
                 undefined
    • Relevant bindings include
        vals :: M.Map (Node g) (MaxBoundedNum (Edge g))
          (bound at WithClass.hs:101:25)
        uset :: S.Set (Node g) (bound at WithClass.hs:101:20)
        dest :: Node g (bound at WithClass.hs:101:15)
        curr :: Node g (bound at WithClass.hs:101:10)
        graph :: g (bound at WithClass.hs:101:4)
        go :: g
              -> Node g
              -> Node g
              -> S.Set (Node g)
              -> M.Map (Node g) (MaxBoundedNum (Edge g))
              -> Maybe (M.Map (Node g) (MaxBoundedNum (Edge g)))
          (bound at WithClass.hs:101:1)
WithClass.hs:102:15:错误:
•无法将类型“边缘g”与“边缘g1”匹配
预期类型:可能(MaxBoundedNum(边g1))
实际类型:可能(MaxBoundedNum(边g))
注:“边”是一个非内射型族
•在“do”块的stmt中:
currDist可能(M.Map(节点g)(MaxBoundedNum(边g)))
(以班级为界。hs:101:1)
我看了一下,但被接受的答案只是说添加了
TypeFamilyDependencies
语言扩展,这似乎对我没有任何帮助。我做错了什么?如何修复代码?提前感谢。

集合(节点g)
映射(节点g)
的操作要求您能够比较节点。这就是
Ord(节点g)
约束所表示的内容。您为
go
指定的类型表示它适用于
节点g
的任何定义,即使是无法比较的定义。错误告诉您,当使用
M.lookup
时,需要
Ord(节点g)
约束,但无法满足它

您可以通过将其添加到
go
的签名来满足该约束:

{-# LANGUAGE FlexibleConstraints #-}  -- Also enable this extension

go :: (Graph g, Ord (Node g)) => ...

这很有道理,我想知道它是如何知道
节点
边缘
类型上的约束的,我只是假设它是从
实例
定义隐式获取的。感谢您的回复对于任何遇到此问题的人,我想这意味着我的
go
类型签名应该是
go:(图g,Ord(Node g),Num(Edge g),Ord(Edge g))=>g->(Node g)->(Node g)->S.Set(Node g)->M.Map(Node g)(MaxBoundedNum(Edge g))->可能(M.Map(Node g)(MaxBoundedNum(Edge g))
{-# LANGUAGE FlexibleConstraints #-}  -- Also enable this extension

go :: (Graph g, Ord (Node g)) => ...