haskell - 类中的部分评估类型
问题描述
这是我在这里提出的问题的具体版本。我有一个算法可以产生一些输出并且可以产生一些辅助信息,在给定的情况下我可能关心也可能不关心(我在下面将此辅助信息称为“注释”)。我正在使用 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
返回一个which 可以是 gcd g,或者它可以另外计算它走了多少步,或者它还可以提供系数 k,l 使得 g = k * a + l *乙:AnnotatedGcd
GcdOnly
GcdWithSteps
GcdExtended
*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 a
,以及Class b
如何将元组(a,b)
转换为两个类的实例(一个关于第一个参数,一个关于第二个参数)。
解决方案
推荐阅读
- javascript - PHP将文件发送到Web服务器无法访问的浏览器
- jquery - 当您在每个循环中修改 jQuery 集合时,是包含修改后的集合还是仅包含原始集合?
- vue.js - 无法在 vuetify 项目中添加自定义颜色
- git - Git rebase to orphan 导致二进制文件冲突
- c# - 可空值类型上的提升运算符是否使用短路?
- php - 在每个函数调用中重新加载使用“require”检索的 php 文件
- arrays - 在 python 逻辑中接受多个输入
- c# - 我应该如何编写一个函数(n)来计算仅包含 1、3、4 的所有可能序列
- c++ - 在 Eigen3 中实现 Bartels–Stewart 算法——仅实矩阵?
- c++ - 在链接可执行文件之前查找静态库未解析的依赖项