Haskell中自定义列表中的乘法元素
我试图在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的长度
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]