我正在尝试编写一个函数来比较两个给定图中节点的度数列表,以进行同构的充分性测试,但我注意到以下代码抛出了与degs
类型相关的错误:
import Data.List
degreeNumbers :: (Eq a) => Graph a -> [Int]
degreeNumbers g = ...
isoByDegree :: (Eq a, Eq b) => Graph a -> Graph b -> Bool
isoByDegree g1 g2 = degs g1 == degs g2
where degs = sort . degreeNumbers
即使我尝试将degs
绑定到像
where degs = (sort . degreeNumbers) :: (Eq c) => Graph c -> [Int]
它仍然表示在应用于Graph a
时,它会期待Graph b
而不是g2
。当然,这是
isoByDegree g1 g2 = (sort . degreeNumbers) g1 == (sort . degreeNumbers) g2
但我想知道绑定方法出了什么问题。
答案 0 :(得分:6)
这是由可怕的monomorphism restriction引起的。使用NoMonomorphismRestriction
禁用它。
{-# LANGUAGE NoMonomorphismRestriction #-}
import Data.List
type Graph a = [a]
degreeNumbers :: (Eq a) => Graph a -> [Int]
degreeNumbers g = undefined
isoByDegree :: (Eq a, Eq b) => Graph a -> Graph b -> Bool
isoByDegree g1 g2 = degs g1 == degs g2
where degs = sort . degreeNumbers
如果您不想禁用monomorhism限制,可以为degs
声明一个显式签名。
isoByDegree :: (Eq a, Eq b) => Graph a -> Graph b -> Bool
isoByDegree g1 g2 = degs g1 == degs g2
where
degs :: (Eq c) => Graph c -> [Int]
degs = sort . degreeNumbers
在声明的右侧添加签名只会在右侧为表达式提供一个显式类型(与推断的类型相同);它不会使degs
声明多态。
答案 1 :(得分:2)
因为你在方程的右边而不是左边给出了一个类型声明,所以Haskell仍然使用类型推断来计算degs
的类型。并且由于单态性限制,它只会推断出一种单态类型,而不是“看起来”像一个函数。修复是明确注释您命名的内容,而不是您为其名称赋予的值:
isoByDegree :: (Eq a, Eq b) => Graph a -> Graph b -> Bool
isoByDegree g1 g2 = degs g1 == degs g2
where degs :: (Eq c) => Graph c -> [Int]
degs = sort . degreeNumbers