[英]Haskell instance declaration affecting interpretation of class
除非删除实例声明,否则下面的代码给我这个错误。 另外,我不知道对Google会做什么,因为错误与造成问题的原因无关?
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)
至于不使用新类型,并使用特定实例声明的动机,我有很多为整数编写的现有代码,我也想将其推广到多项式,而且我不想用包装和拆开新类型将其重写为丑陋的混乱。
如果有另一个解决方案可以实现我想要的功能,那也将不胜感激。
我不确定您为什么认为需要新的类型。
“超类实例”
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
这使得显式实例化更加易于管理,并且还使您可以声明结构的更多合成属性。 (参见这篇文章 ,其中的类型化实例可以使您受益匪浅)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.