Haskell中自定义列表中的乘法元素

Haskell中自定义列表中的乘法元素,haskell,functional-programming,Haskell,Functional Programming,我试图在Haskell中为我的自定义列表数据类型实现一个自定义乘法运算,它使用Int和[Int] Int用于通过模除法减少整数,我将称之为d [Int]表示列表的内容 假设a和b是两个具有相同d的列表 a的长度为w,b的长度为v c=a*b是: c[k] = a[0] * b[k] + a[1] * b[k - 1] + a[2] * b[k - 2] + · · · + a[k] * b[0] 最后,c[k]减少mod d c=w+v-1的长度 这意味着c[k]中的索引k可以大于w和v的长度

我试图在Haskell中为我的自定义列表数据类型实现一个自定义乘法运算,它使用
Int
[Int]

Int
用于通过模除法减少整数,我将称之为
d

[Int]
表示列表的内容

假设
a
b
是两个具有相同
d
的列表
a
的长度为
w
b
的长度为
v

c=a*b
是:

c[k] = a[0] * b[k] + a[1] * b[k - 1] + a[2] * b[k - 2] + · · · + a[k] * b[0]
最后,
c[k]
减少
mod d

c=w+v-1的长度

这意味着
c[k]
中的索引
k
可以大于
w
v
的长度
为了解决这个问题,我连接了一个包含0个元素的列表,用于原始列表边界之外的索引

澄清:

c[0] = (a[0] * b[0]) % d  
c[1] = (a[0] * b[1] + a[1] * b[0]) % d  
c[2] = (a[0] * b[2] + a[1] * b[1] + a[2] * b[0]) % d  
.  
.  
.  
c[w + v - 1]
例如,
a=[3,2,4]
b=[7,9,7,2]
,两者都有
d=31

在代码中,当它们相乘时,它们是
[3,2,4,0,0,0]
[7,9,7,2,0,0]

在这个例子中,
c=a*b=[21,10,5,25,1,8]

这是我的代码:

module Custom where

    data CustomList = CustomList Int [Int]
    instance Num CustomList where
        (CustomList a1 b1) * (CustomList a2 b2) = 
            if length b1 >= 1 && length b2 >= 1  then do 
                let llen = (length b1) + (length b2) - 1

                --concatenating a list of 0 elements for indices outside the bounds of the original list. 
                let sub_b1 = llen - (length b1)
                let sub_b2 = llen - (length b2)
                let zeros_b1 = map (0*) [1..sub_b1]
                let zeros_b2 = map (0*) [1..sub_b2]

                --matching list lengths
                let new_b1 = b1++zeros_b1
                let new_b2 = b2++zeros_b2

                --trying to mimic a nested for loop
                let ans = [ (new_b1 !! x) * (new_b2 !! y) | x <- [0..llen-1], y <- (reverse [0..x]) ]

                CustomList (a1) (map (`mod` (a1)) ans)
            else do
                0

    instance Show CustomList where
        show (CustomList a b) = "output: " ++ (show b) ++ "\nlength: " ++ (show a)
不正确(我得到的)

正确(我应该得到什么)

我意识到我的逻辑中存在一些问题:

  • x
    计数器中,对于所有
    c[k]
    计算,我需要从
    a[0]
    开始,在
    a[k]
    结束,但我从
    a[x]
    开始
  • 答案没有汇总在一起。例如,我不是获得
    c[1]=a[0]*b[1]+a[1]*b[0]
    ,而是获得
    c[1]=a[0]*b[1]
    &
    c[2]=a[1]*b[0]
  • 我不知道如何解决它,我一直在尝试,最终只是通过尝试去做来制造新的问题

    我是Haskell的新手,所以我更喜欢用一种简单易读的方法来解决这个问题,而不是用更“Haskell”的方法。 但任何帮助都将受到感谢,请提前感谢。

    简单明了:

    data CustomList = CustomList Int [Int] deriving(Show)
    
    instance Num CustomList where
      CustomList a1 b1 * CustomList a2 b2 = CustomList a1 (map (`mod` a1) ans)
        where ans = map getAnsElem [1..length b1 + length b2 - 1]
              getAnsElem k = sum $ zipWith (*) (withLength k b1) (reverse $ withLength k b2)
              withLength n xs = take n (xs ++ repeat 0)
    
    测试它:

    λ> CustomList 31 [3,2,4] * CustomList 31 [7,9,7,2]
    CustomList 31 [21,10,5,25,1,8]
    
    说明:

    • withLength
      获取一个列表并将其设置为给定长度,如果列表太长,则将其截断;如果列表太短,则用零填充
    • zipWith
      获取两个列表并并行遍历它们,使用给定的函数组合元素
    • 您的列表理解方法失败的一个原因是因为
      [f x y | x
      
      output: [21, 10, 5, 25, 1, 8]  
      length: 6  
      
      data CustomList = CustomList Int [Int] deriving(Show)
      
      instance Num CustomList where
        CustomList a1 b1 * CustomList a2 b2 = CustomList a1 (map (`mod` a1) ans)
          where ans = map getAnsElem [1..length b1 + length b2 - 1]
                getAnsElem k = sum $ zipWith (*) (withLength k b1) (reverse $ withLength k b2)
                withLength n xs = take n (xs ++ repeat 0)
      
      λ> CustomList 31 [3,2,4] * CustomList 31 [7,9,7,2]
      CustomList 31 [21,10,5,25,1,8]
      
      getAnsElem k = sum [x * y | x <- withLength k b1 | y <- reverse $ withLength k b2]