我试图表示加权边。我最终想让OutE成为Eq和Ord的一个实例,其约束条件是etype是Eq和Ord的一个实例。假设我有以下文件作为temp.hs:
data (Ord etype)=> OutE vtype etype = OutE {destVertex:: vtype, edgeValue::etype}
applyFunBy accessor ordfun = (\x y -> (ordfun (accessor x) (accessor y)))
instance Eq (OutE vtype etype) where
--(==) :: Ord etype => (OutE vtype etype) -> (OutE vtype etype) -> Bool
--(/=) :: Ord etype => (OutE vtype etype) -> (OutE vtype etype) -> Bool
(==) = applyFunBy edgeValue (==)
(/=) = applyFunBy edgeValue (/=)
当我在ghci中加载它时,我收到以下错误:
temp.hs:10:19:
Could not deduce (Ord etype)
from the context (Eq (OutE vtype etype))
arising from a use of `edgeValue' at temp.hs:10:19-27
Possible fix:
add (Ord etype) to the context of the instance declaration
In the first argument of `applyFunBy', namely `edgeValue'
In the expression: applyFunBy edgeValue (==)
In the definition of `==': == = applyFunBy edgeValue (==)
temp.hs:11:19:
Could not deduce (Ord etype)
from the context (Eq (OutE vtype etype))
arising from a use of `edgeValue' at temp.hs:11:19-27
Possible fix:
add (Ord etype) to the context of the instance declaration
In the first argument of `applyFunBy', namely `edgeValue'
In the expression: applyFunBy edgeValue (/=)
In the definition of `/=': /= = applyFunBy edgeValue (/=)
Failed, modules loaded: none.
如果包含(==)和(\ =)类型签名的行,我会得到:
temp.hs:6:1:
Misplaced type signature:
== ::
(Ord etype) => (OutE vtype etype) -> (OutE vtype etype) -> Bool
temp.hs:7:1:
Misplaced type signature:
/= ::
(Ord etype) => (OutE vtype etype) -> (OutE vtype etype) -> Bool
答案 0 :(得分:6)
您在etype
的定义中将Ord
限制为OutE
:
data (Ord etype) => OutE vtype etype = ...
但是在Eq
实例中,您实际上是在尝试无限制地为任何 etype
定义实例。
instance Eq (OutE vtype etype) where
当然这不起作用,因为OutE
本身只是为Ord etype
定义的,因此您还必须将类型类约束添加到实例定义中。
instance (Ord etype) => Eq (OutE vtype etype) where
请注意,==
或/=
的一个定义足以使类型类工作。
请注意,它通常更容易,因此被认为是更好的样式,不在data
- 类型上有类型类约束,而只是在实际需要类型类功能的实例/方法上。
在许多情况下,一个人不需要约束,最终会得到不必要的笨拙类型签名。
拿走,例如一些有序的地图类型Ord key => Map key value
。
如果我们只想列出所有密钥怎么办?或者获得元素的数量?我们不需要Ord
这些键,所以为什么不让地图不受限制地使用简单的
getKeys :: Map key value -> [key]
getLength :: Map key value -> Int
只需在像
这样的函数中真正需要它时添加类型类insert :: Ord key => key -> value -> Map key value
答案 1 :(得分:2)
data (Ord etype)=> OutE vtype etype = OutE {destVertex:: vtype, edgeValue::etype}
第一个问题:这是糟糕的风格。您的数据类型声明不应该有约束。将约束留给函数,就像容器包一样。
instance Eq (OutE vtype etype) where
第二个“问题”。您可以在数据声明后添加deriving (Eq)
。我猜你知道这一点,并且正在为你自己的学习明确写出这个实例(对你有好处)......
instance Eq (OutE vtype etype) where
(==) = applyFunBy edgeValue (==)
(/=) = applyFunBy edgeValue (/=)
第三个问题:如果属于Eq
类,则无法比较权益值。所以你想说etype
受到Eq:
instance (Eq etype) => Eq (OutE vtype etype) where
(==) = applyFunBy edgeValue (==)
(/=) = applyFunBy edgeValue (/=)
第四,您实际上不需要为(==)和(/ =)编写实例。一旦您定义了其中一个,默认值就会起作用。