首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >访问返回值的虚拟类型

访问返回值的虚拟类型
EN

Stack Overflow用户
提问于 2013-02-20 12:21:37
回答 2查看 234关注 0票数 2

下面是一个模仿Data.Fixed的模块化算术Num实例的实现。

我想写一个fromRational的替代实现,它看起来像这样:

代码语言:javascript
复制
fromRational r = case invertMod (denominator r) theModulus of
                   Just inv -> normalize $ (numerator r) * inv
                   Nothing -> error "..."

但是我不知道我会在theModulus中使用什么。与其他类型类函数不同,我没有可以调用modulusModular a类型的值。

代码语言:javascript
复制
{-# LANGUAGE NoMonomorphismRestriction #-}

import Math.NumberTheory.Moduli (invertMod)
import Data.Ratio (numerator, denominator)

class HasModulus a where
  modulus :: p a -> Integer

withType :: (p a -> f a) -> f a
withType foo = foo undefined

withModulus :: (HasModulus a) => (Integer -> f a) -> f a
withModulus foo = withType (foo . modulus)

newtype Modular a = M Integer

normalize :: HasModulus a => Integer -> Modular a
normalize x = withModulus $ \m -> M (x `mod` m)

instance (HasModulus a) => Num (Modular a) where
  (M a) + (M b) = normalize (a+b)
  (M a) - (M b) = normalize (a-b)
  (M a) * (M b) = normalize (a*b)
  negate (M a)  = normalize (-a)
  abs           = id
  signum _      = fromInteger 1
  fromInteger   = normalize

instance (HasModulus a) => Fractional (Modular a) where
  recip ma@(M a) = case invertMod a (modulus ma) of
                     Just inv -> normalize $ inv
                     Nothing  -> error "divide by zero error"
  ma / mb        = ma * (recip mb)
  fromRational r = (fromInteger $ numerator r) / (fromInteger $ denominator r)

instance (HasModulus a) => Show (Modular a) where
  show mx@(M x) = (show x) ++ " mod " ++ (show $ modulus mx)

data M5 = M5
data M7 = M7

instance HasModulus M5 where modulus _ = 5
instance HasModulus M7 where modulus _ = 7

bar = 1 / 3

main = do print $ (bar :: Modular M5)
          print $ (bar :: Modular M7)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-02-20 21:12:16

编写更接近初始fromRational的Ansatz的方法是

代码语言:javascript
复制
fromRational r = let x = case invertMod (denominator r) (modulus x) of
                           Just inv -> normalize $ (numerator r) * inv
                           Nothing -> error "..."
                 in x

因为结果是Modular a类型的,所以我们可以从它获得模量(不需要检查它)。所以我们所需要的就是给它命名,这样我们就可以在需要的地方引用它。

票数 1
EN

Stack Overflow用户

发布于 2013-02-20 12:35:30

我想通了..。关键是使用withModulus函数:

代码语言:javascript
复制
mdivide :: HasModulus a => Integer -> Integer -> Modular a
mdivide x y = withModulus $ M . mdiv' x y
                where mdiv' x y m =
                        case invertMod y m of
                          Just inv -> (x * inv) `mod` m
                          Nothing  -> error "..."

然后..。

代码语言:javascript
复制
fromRational r = mdivide (numerator r) (denominator r)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14972243

复制
相关文章

相似问题

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