如何以无点风格在Haskell中定义点积?求fold与zipWith无点组合方案
解决Haskell中fold与zipWith的无点函数组合问题
嘿,我来帮你搞定这个无点形式的函数组合问题!先回顾一下你现有的代码:
zWMult :: Num c => [c] -> [c] -> [c] zWMult = zipWith (*) foldPl0 :: Num c => [c] -> c foldPl0 = foldl (+) 0 -- 带参数的正确实现 dPr x y = foldPl0 (zWMult x y)
你想要把dPr改成完全无点的形式,核心在于利用Haskell的柯里化特性和函数组合运算符(.)的嵌套使用。我们可以一步步推导出来:
推导步骤
第一步:用函数组合替换括号应用
原代码里的foldPl0 (zWMult x y)可以看成是foldPl0作用于zWMult x y的结果,而zWMult x y其实是zWMult x这个一元函数作用于y的结果。根据函数组合(.)的定义(f . g) a = f (g a),我们可以把式子改写为:dPr x y = (foldPl0 . zWMult x) y第二步:移除参数y
既然等式两边都把y作为参数,我们可以直接把y去掉,得到:dPr x = foldPl0 . zWMult x第三步:嵌套函数组合移除参数x
现在看foldPl0 . zWMult x,这其实是(foldPl0 .)这个函数作用于zWMult x的结果。而zWMult x又是zWMult作用于x的结果,所以我们可以再次用函数组合把这部分包装起来:dPr x = ((foldPl0 .) . zWMult) x最后把两边的
x去掉,就得到了完全无点的版本:dPr = (foldPl0 .) . zWMult
验证正确性
我们可以测试一下这个无点版本是否和带参数的版本行为一致:
-- 带参数版本:dPr [1,2,3] [4,5,6] = 1*4 + 2*5 + 3*6 = 32 -- 无点版本:((foldPl0 .) . zWMult) [1,2,3] [4,5,6] = 32
结果完全一致,说明这个无点实现是正确的。
为什么直接用foldPl0 . zWMult不行?
你之前尝试的失败大概率是因为直接用了foldPl0 . zWMult,但这个写法类型不匹配:
zWMult的类型是[c] -> [c] -> [c],它接受一个列表后返回另一个函数[c] -> [c]foldPl0的类型是[c] -> c,它需要的输入是一个列表- 函数组合
(.)要求右边函数的输出类型等于左边函数的输入类型,这里显然不满足,所以会报错。而嵌套的(foldPl0 .) . zWMult则是把zWMult的二元应用结果(也就是最终的列表)传递给foldPl0,完美匹配类型。
内容的提问来源于stack exchange,提问作者user5775230
相关产品推荐
相关产品推荐

