首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有没有可能有一个“本地”类型类实例?

有没有可能有一个“本地”类型类实例?
EN

Stack Overflow用户
提问于 2012-03-03 19:44:59
回答 1查看 1.3K关注 0票数 20

我的意思是定义一个在函数的局部(letwhere)作用域中应用的类型类的实例。更重要的是,我希望这个实例中的函数是闭包的,即能够关闭定义实例的词法作用域中的变量(这意味着下次调用该实例所在的函数时,该实例可能会以不同的方式工作)。

我可以为您提供一个简化的用例。假设我有一个函数,它基于一个类型类对一个类型进行操作。在这个例子中,我使用了平方,它可以在任何实例Num的类型上操作(是的,平方非常简单,可以很容易地重新实现,但它代替了一些可能更复杂的东西)。我需要能够按原样使用现有函数(无需更改或重新实现它)。

代码语言:javascript
复制
square :: Num a => a -> a
square x = x * x

现在,假设我希望在模算术中使用这个操作,即加法、乘法等对某个数字取模。这对于任何固定的模基都很容易实现,但我想要有一些通用的东西,我可以在不同的模基上重用。我希望能够定义这样的东西:

代码语言:javascript
复制
newtype ModN = ModN Integer deriving (Eq, Show)

-- computes (x * x) mod n
squareModN :: 
squareModN x n =
  let instance Num ModN where
    ModN x * ModN y = ModN ((x * y) `mod` n) -- modular multiplication
    _ + _ = undefined         -- the rest are unimplemented for simplicity
    negate _ = undefined
    abs _ = undefined
    signum _ = undefined
    fromInteger _ = undefined
  in let ModN y = square (ModN x)
     in y

这样做的要点是,我需要使用上面的函数(square),该函数要求其参数是某个类型类的实例的类型。我定义了一个新类型并使其成为Num的实例;然而,为了使它正确地执行模运算,它依赖于模基n,由于此函数的通用设计,它可能会因调用而改变。我希望将实例函数定义为square函数的一种一次性“回调”(如果您愿意的话),以自定义它这次(且仅此一次)如何执行操作。

一种解决方案可能是将“闭包变量”直接集成到数据类型本身中(例如,ModN (x, n)表示数字及其所属的基数),并且操作可以从参数中提取这些信息。然而,这有几个问题: 1)对于多参数函数(例如(*)),它需要在运行时检查这些信息是否匹配,这很丑陋;2)实例可能包含我可能希望依赖于闭包变量的0参数“值”,但由于它们不包含参数,因此无法从参数中提取它们。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-03-03 20:34:19

建议的扩展具有我的this previous answer中演示的相同问题;您可以使用本地实例创建具有相同键类型但不同Ord实例的两个Map,从而导致所有不变量崩溃。

但是,reflection包允许您定义这样的ModN类型:使用Reifies约束定义单个实例,并使用reify激活特定n的实例。(我相信implicit parameters也会让这成为可能,但这个扩展很少使用。)

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9545866

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档