如何(即派生)Rational和新类型的乘法(使用*)

时间:2015-12-24 09:02:07

标签: haskell typeclass

我正在实现一个小程序来处理多项式运算,其灵感来自于upenn cis194的一个赋值。代码如下(我省略了一些不相关的代码):

newtype Poly = Poly [Rational]
    deriving Eq
s :: Poly
s = Poly [1, 0]

instance Num Poly where
    (Poly a) + (Poly b) = ...
    (Poly a) * (Poly b) = ...
    negate (Poly xs) = ...
    fromInteger i = Poly [fromInteger i]

instance Fractional Poly where
    fromRational f = Poly [fromRational f]

instance Show Poly where
    show (Poly a) = ...

pdiv :: Poly -> Poly -> (Poly, Poly)
pdiv (Poly a) (Poly b) = ...

cauer1 :: Poly -> Poly -> String
cauer1 a b =
    let (q, r) = pdiv a b
    in if r == 0 then (show q) else
        (show q) ++ " + 1/(" ++ (cauer1 b r) ++ ")"

此代码有效。例如,我可以得到多项式结果的长除法,以便使用cauer1函数制作Cauer 1形式电路。 (电路分析)

ghci > let a = Poly [1, 23%6, 10%3, 0] -- represents: s^3 + 23/6 s^2 + 10/3 s
ghci > let b = Poly [1, 3, 2]
ghci > cauer1 a b
"s + 1/(6%5 + 1/(25%42s + 1/(49%5 + 1/(1%14s))))"

我现在要做的是做这样的事情:

ghci > cauer1 (s^3 + 23%6*s^2 + 10%3*s) (s^2 + 3*s + 2)

并获得相同的结果。

在制作Poly Poly [Double]Poly实例并实施Num和{后,我的Fractional类型定义为fromInteger {1}},我可以执行fromRationals * 1s * 2.3之类的操作,然后强大的类型类会将它们计算为3.4 * s^2而没有任何问题。但是通过这种方式,结果是所有小数和丢失精度,这就是我切换到Poly的原因。但现在我无法做Poly [Rational],他们只是根据ghc键入不匹配:

3%2 * s

我发现<interactive>:1:9: Couldn't match expected type ‘Ratio a’ with actual type ‘Poly’ In the second argument of ‘(*)’, namely ‘s’ In the expression: (3 % 2) * s RationalRatio IntegerRatioNum的实例,为什么这不起作用,我该如何修复它?

1 个答案:

答案 0 :(得分:1)

  

我可以执行类似s * 1s * 2.33.4 * s^2 ...

的操作

是的,因为(引用Prelude文档):

  

浮动文字表示将fromRational应用于Rational类型的值,因此此类文字的类型为(Fractional a) => a

..这意味着您可以在任何地方使用Poly(作为Fractional的子类)

的地方使用这样的文字

同样的举例不适用于3%2,这不是文字,而是类型Integral a => Ratio a的表达式,这只表示我可以在任何地方使用这样的表达式我可以使用Ratio a(提供aIntegral)。这远没那么灵活。

然后,您需要的是一个运算符%3%2将获得一个(Fractional a) => a类型,就像文字3.14

一样

这可以通过重新定义来完成,如下例

import qualified Data.Ratio as R

(%) :: Fractional a => Integer -> Integer -> a
x % y = fromRational ((R.%) x y)

-- the rest as in your example

现在你可以做到

*YourExample> :t 3%2 * s -- ask ghci whether this makes sense ...
3%2 * s :: Poly          -- yes, it does!