繁体   English   中英

Haskell实例声明影响类的解释

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM