乘以流(表示多项式系数)

时间:2014-10-27 01:02:17

标签: haskell

对于2013年homework,我试图将2个Streams相乘。

xStream :: Stream Integer
xStream = Cons 0 (Cons 1 $ streamRepeat 0)

instance Num (Stream Integer) where
    fromInteger x = Cons x $ streamRepeat 0
    negate        = streamMap (* (-1)) 
    (+) xs ys     = combineStreams (+) xs ys
    (*) xs ys     = multStreams xs ys
    abs           = streamMap abs

以下是教授对如何实现上述流的乘法的帮助:

 Multiplication is a bit trickier. Suppose A = a0 + xA` and B = b0 +
 xB0 are two generating functions we wish to multiply. We reason as
 follows: AB = (a0 + xA`)B   
             = a0B + xA`B    
             = a0(b0 + xB0) + xA`B   
             = a0b0 + x(a0B0 + A`B)

这是我的尝试:

multStreams :: Stream Integer -> Stream Integer -> Stream Integer
multStreams (Cons x xs) b@(Cons y ys) = addXY + rest
  where addXY = Cons (x + y) $ streamRepeat 0 
        rest  = (xStream *) $ (streamMap (*x) ys + (xs * b))

具有以下定义:

data Stream a = Cons a (Stream a)

streamRepeat :: a -> Stream a
streamRepeat x = Cons x (streamRepeat x)    

streamMap :: (a -> b) -> Stream a -> Stream b
streamMap f (Cons x xs) = Cons (f x) rest
   where rest = streamMap f xs

combineStreams :: (a -> b -> c) -> Stream a -> Stream b -> Stream c
combineStreams f (Cons x xs) (Cons y ys) = Cons (f x y) rest
   where rest = combineStreams f xs ys

请注意,xStream与此related questionx相同。

当我尝试上述实现时,我对multStreams的调用不会终止。

请帮助我了解上述multStream功能的错误 - 在实施中以及我是否正确实施了教授对乘法的解释。

1 个答案:

答案 0 :(得分:4)

根本问题是,multStreams的定义在(*)的定义中直接使用Stream上的rest,这不是给定推理的意图

如果你考虑等式AB = a0b0 + x(a0B0 + A'B),它会告诉你AB的第一项应该是什么:a0b0是常数,即第一项的一部分,以及其他每一项流中的术语乘以x,即不是第一个术语的一部分。

它还告诉您AB剩余条款来自a0B0 + A'B - 因为将其与Cons一起移动相当于multipltying x

与您所做的完全不同的是,输出流的第一个元素可以在不对(*)进行任何递归调用的情况下构建,即使其余元素使用一个。

所以这样的事情应该有效:

multStreams :: Stream Integer -> Stream Integer -> Stream Integer
multStreams (Cons x xs) b@(Cons y ys) =
    Cons (x * y) (streamMap (*x) ys + multStreams xs b)