类中的部分评估类型

时间:2020-02-05 16:03:46

标签: haskell types

这是我的问题here的具体版本。我有一个算法,该算法可以产生一些输出,并且可以产生一些辅助信息,在给定的情况下,我可能会或可能不会关心这些信息(我在下文中将此辅助信息称为“注释”)。我正在使用Euclid算法进行说明:

class AnnotatedGcd m where
    actually :: (Integral a) => a -> m a
    update :: (Integral a) => a -> m a -> m a

newtype GcdOnly a = Gcd a deriving Show

instance AnnotatedGcd GcdOnly where
    actually = Gcd
    update q = id

newtype GcdWithSteps a = GcdS (a, Int) deriving Show

instance AnnotatedGcd GcdWithSteps where
    actually x = GcdS (x, 0)
    update q (GcdS (x, s)) = GcdS (x, s+1)

newtype GcdExtended a = GcdE (a, a, a) deriving Show

instance AnnotatedGcd GcdExtended where
    actually x = GcdE (x, 1, 0)
    update q (GcdE (x, k, l)) = (GcdE (x, l, k - q*l))

gcd :: (Integral a, AnnotatedGcd m) => a -> a -> m a
gcd a b = if b == 0 then actually a else update q ((Main.gcd) b r)
  where q = a `div` b
        r = a `rem` b

函数gcd a b返回一个AnnotatedGcd,在示例中可以是GcdOnly,它仅仅是gcd g,或者可以是GcdWithSteps,另外还要计算多少步花费了,或者也可能GcdExtended还提供了系数k,l,使得g = k * a + l * b:

*Main> (Main.gcd 253 83) :: (GcdOnly Int)
Gcd 1
*Main> (Main.gcd 253 83) :: (GcdWithSteps Int)
GcdS (1,4)
*Main> (Main.gcd 253 83) :: (GcdExtended Int)
GcdE (1,21,-64)

现在,如果我想计算步数并获得系数怎么办?与其继续写越来越多的AnnotatedGcd实例,不如我想有一个注释的概念,并说注释的元组再次是注释:

class GcdAnnotation a where
    emptyAnnotation :: a
    annotate :: Integral b => b -> a -> a

instance (GcdAnnotation a, GcdAnnotation b) => GcdAnnotation (a,b) where
    emptyAnnotation = (emptyAnnotation, emptyAnnotation)
    annotate q (x, y) = (annotate q x, annotate q y)

instance (GcdAnnotation a, GcdAnnotation b, GcdAnnotation c) => GcdAnnotation (a,b,c) where
    emptyAnnotation = (emptyAnnotation, emptyAnnotation, emptyAnnotation)
    annotate q (x, y, z) = (annotate q x, annotate q y, annotate q z)

instance GcdAnnotation b => AnnotatedGcd (,b) where
    actually x = (x, emptyAnnotation)
    update q (g, x) = (g, annotate q x)

这是有效的Haskell代码,但最后一个实例声明除外。问题是:一个人怎么才能真正发表这样的声明?

通用版本为:给定两个参数类Class aClass b,如何将元组(a,b)变成两个类的实例(一个关于第一个参数,一个关于尊重第二个。

0 个答案:

没有答案