除非删除实例声明,否则下面的代码会给出此错误。另外,我不知道谷歌会发生什么,因为错误与导致问题的原因无关?
Test.hs|20 col 31 error| Could not deduce (Integral a) arising from a use of `gendivmod'
|| from the context (Euclidean a)
|| bound by the type signature for
|| gcdBezouts :: Euclidean a => a -> a -> (a, a, a)
|| at /home/jragonfyre/src/haskell/mathlib/Test.hs:17:15-50
|| Possible fix:
|| add (Integral a) to the context of
|| the type signature for
|| gcdBezouts :: Euclidean a => a -> a -> (a, a, a)
|| In the expression: gendivmod x y
|| In a pattern binding: (q, r) = gendivmod x y
|| In the expression:
|| let
|| (q, r) = gendivmod x y
|| (n, m, d) = gcdBezouts y r
|| in (m, n - m * q, d)
这是一个在我的机器上重现错误的MWE。
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
class (Num a, Eq a) => Euclidean a where
genmod :: a -> a -> a
genmod a = snd . gendivmod a
gendiv :: a -> a -> a
gendiv a = fst . gendivmod a
gendivmod :: a -> a -> (a,a)
gendivmod a b = (gendiv a b, genmod a b)
isUnitEu :: a -> Bool
isUnitEu = (==1) . abs
instance (Integral a) => Euclidean a where
gendivmod = divMod
gcdBezouts :: (Euclidean a) => a -> a -> (a, a, a)
gcdBezouts 0 x = (0, 1, x)
gcdBezouts x 0 = (1, 0, x)
gcdBezouts x y = let (q, r) = gendivmod x y
(n, m, d) = gcdBezouts y r
in (m, n-m*q, d)
至于不使用newtype的动机,以及特定的实例声明,我有很多为整数编写的现有代码,我想要推广使用多项式,而且我没有&#39 ; t想要将包装和展开新类型重写为一个丑陋的混乱。
如果有另一种解决方案可以实现我的目标,那也值得赞赏。
答案 0 :(得分:4)
我不确定你为什么认为你需要一个新类型。
“超类实例”
instance (Integral a) => Euclidean a where
您可能认为“Integral
的每个实例也是Euclidean
的实例”实际上意味着“每个类型都是Euclidean
的实例,稍后添加约束,在实例化时我们需要Integral
“。这种情况总是会给你带来麻烦。
我建议明确地在您需要的每种类型中实例化Euclidean
(这也允许您摆脱UndecidableInstances
)。
instance Euclidean Integer where
...
如果您在许多Integral
类型中实例化它,您应该编写帮助程序:
integralGenmod :: (Integral a) => a -> a -> a
...
或者,既然你的班级有很多方法,那就从启示:
开始data EuclideanDomain a = EuclideanDomain a {
edGenmod :: a -> a -> a,
...
}
class Euclidean a where
euclideanDomain :: EuclideanDomain a
genmod :: (Euclidean a) => a -> a -> a
genmod = edGenmod euclideanDomain
...
integralEuclidean :: (Integral a) => EuclideanDomain a
integralEuclidean = EuclideanDomain { ... }
instance Euclidean Integral where
euclideanDomain = integralEuclidean
这使得显式实例化更易于管理,并且还允许您声明结构的更多组成属性。 (参见此post,通过对类型类进行实现可以帮助您获得很长的路径)