Haskell 注意:“Edge”是一个非单射类型族
Haskell NB: ‘Edge’ is a non-injective type family
我正在尝试编写我自己的图形库Haskell以供在代码出现时使用。我正在尝试对图表使用 class,并使用 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 算法中未访问节点的 Infinity
值,我创建了一个求和数据类型:
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
这似乎适用于 graph g
,其中 graph :: MapGraph Int String
go graph
:: [Char]
-> [Char]
-> S.Set [Char]
-> M.Map [Char] (MaxBoundedNum Int)
-> Maybe (M.Map [Char] (MaxBoundedNum Int))
我的 go
函数的下一部分需要从 vals
地图查找当前距离。
currDist <- M.lookup curr vals
如果我执行以下操作,这将在 go
函数之外工作:
currDist = M.lookup current vals
*Main> :t currDist
currDist :: Maybe (MaxBoundedNum Integer)
然而,在 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
Could not deduce
部分让我觉得我需要给它一个类型注释,所以我这样做了:
currDist <- M.lookup curr vals :: Maybe (MaxBoundedNum (Edge g))
但这给了我这个错误:
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)
我查看了 ,但接受的答案只是说要添加 TypeFamilyDependencies
语言扩展,这似乎对我没有任何作用。我做错了什么以及如何修复我的代码?提前谢谢你。
Set (Node g)
和 Map (Node g)
上的操作要求您能够比较节点。这就是 Ord (Node g)
约束所代表的意思。您为 go
提供的类型表示它适用于 any 定义的 Node g
,即使是那些无法比较的定义。该错误告诉您,当您使用 M.lookup
时,需要 Ord (Node g)
约束,但无法满足它。
您可以通过将其添加到 go
的签名来满足该约束:
{-# LANGUAGE FlexibleConstraints #-} -- Also enable this extension
go :: (Graph g, Ord (Node g)) => ...
我正在尝试编写我自己的图形库Haskell以供在代码出现时使用。我正在尝试对图表使用 class,并使用 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 算法中未访问节点的 Infinity
值,我创建了一个求和数据类型:
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
这似乎适用于 graph g
,其中 graph :: MapGraph Int String
go graph
:: [Char]
-> [Char]
-> S.Set [Char]
-> M.Map [Char] (MaxBoundedNum Int)
-> Maybe (M.Map [Char] (MaxBoundedNum Int))
我的 go
函数的下一部分需要从 vals
地图查找当前距离。
currDist <- M.lookup curr vals
如果我执行以下操作,这将在 go
函数之外工作:
currDist = M.lookup current vals
*Main> :t currDist
currDist :: Maybe (MaxBoundedNum Integer)
然而,在 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
Could not deduce
部分让我觉得我需要给它一个类型注释,所以我这样做了:
currDist <- M.lookup curr vals :: Maybe (MaxBoundedNum (Edge g))
但这给了我这个错误:
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)
我查看了 TypeFamilyDependencies
语言扩展,这似乎对我没有任何作用。我做错了什么以及如何修复我的代码?提前谢谢你。
Set (Node g)
和 Map (Node g)
上的操作要求您能够比较节点。这就是 Ord (Node g)
约束所代表的意思。您为 go
提供的类型表示它适用于 any 定义的 Node g
,即使是那些无法比较的定义。该错误告诉您,当您使用 M.lookup
时,需要 Ord (Node g)
约束,但无法满足它。
您可以通过将其添加到 go
的签名来满足该约束:
{-# LANGUAGE FlexibleConstraints #-} -- Also enable this extension
go :: (Graph g, Ord (Node g)) => ...