如何做(即推导)有理数和新类型的乘法(使用*)
How to do (i.e. derive) multiplication (using *) of a Rational and a new type
我正在实现一个小程序来处理多项式运算,灵感来自 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]
,在创建 Num
和 Fractional
的 Poly
实例并实现 fromInteger
之后和 fromRational
,我可以做类似 s * 1
、s * 2.3
、3.4 * s^2
的事情,然后强大的类型类将毫无问题地将它们计算为 Poly
。但是这样一来结果全是小数,精度不高,所以改成Poly [Rational]
。但是现在我做不到 3%2 * s
,他们只是根据 ghc:
输入不匹配
<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
我发现 Rational
是 Ratio Integer
而 Ratio
是 Num
和 Fractional
的实例,为什么这不起作用,怎么能我修好了吗?
I can do something like s * 1
, s * 2.3
, 3.4 * s^2
...
是的,因为(引自 Prelude 文档):
A floating literal stands for an application of fromRational
to a value of type Rational
, so such literals have type (Fractional a) => a
.
.. 这意味着你可以在任何可以使用 Poly
(作为 Fractional
的子类)
的地方使用这样的文字
这并不适用于例如3%2
,它不是文字,而是类型为 Integral a => Ratio a
的表达式,这只意味着我可以在任何地方使用这样的表达式我可以使用 Ratio a
(前提是 a
Integral
)。这远没有那么灵活。
然后,您需要的是一个运算符 %
,这样 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!
我正在实现一个小程序来处理多项式运算,灵感来自 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]
,在创建 Num
和 Fractional
的 Poly
实例并实现 fromInteger
之后和 fromRational
,我可以做类似 s * 1
、s * 2.3
、3.4 * s^2
的事情,然后强大的类型类将毫无问题地将它们计算为 Poly
。但是这样一来结果全是小数,精度不高,所以改成Poly [Rational]
。但是现在我做不到 3%2 * s
,他们只是根据 ghc:
<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
我发现 Rational
是 Ratio Integer
而 Ratio
是 Num
和 Fractional
的实例,为什么这不起作用,怎么能我修好了吗?
I can do something like
s * 1
,s * 2.3
,3.4 * s^2
...
是的,因为(引自 Prelude 文档):
A floating literal stands for an application of
fromRational
to a value of typeRational
, so such literals have type(Fractional a) => a
.
.. 这意味着你可以在任何可以使用 Poly
(作为 Fractional
的子类)
这并不适用于例如3%2
,它不是文字,而是类型为 Integral a => Ratio a
的表达式,这只意味着我可以在任何地方使用这样的表达式我可以使用 Ratio a
(前提是 a
Integral
)。这远没有那么灵活。
然后,您需要的是一个运算符 %
,这样 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!