这些Haskell高阶函数的Python等效函数是什么?

5

这本书《Haskell趣学指南》中的“偏函数”章节包含以下代码:

multThree :: (Num a) => a -> a -> a -> a
multThree x y z = x * y * z

ghci> let multTwoWithNine = multThree 9
ghci> multTwoWithNine 2 3
54
ghci> let multWithEighteen = multTwoWithNine 2
ghci> multWithEighteen 10
180

我目前在使用Python中的functools库,并成功通过它复制了那些函数的行为。

from functools import partial

def multThree(x,y,z):
  return x * y * z

>>> multTwoWithNine = partial(multThree,9)
>>> multTwoWithNine(2,3)
>>> multWithEighteen = partial(multTwoWithNine,2)
>>> multWithEighteen(10)
180

我现在想做的一件事是看看能否复制同一书章中一些更有趣的高阶函数,例如:

zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' _ [] _ = []
zipWith' _ _ [] = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys

然而,我不确定如何做到这一点,或者partial()是否在这里有用。


1
你应该编辑和修复你的函数,确保它们都是语法正确的。比如说,你的第一个函数缺少了参数。 - Thomas M. DuBuisson
2
从技术上讲,在任何转换中,您都必须使用“partial”,因为所有的Haskell函数都是自动柯里化的,“partial”模拟了柯里化函数部分应用的能力。或者,您可以将Python版本编写为柯里化函数,但是然后您必须像这样调用它们:foo(a)(b)(c) - Wes
2
小提醒:您想要的是“部分应用函数”,而不是“偏函数”。 - Philip JF
4个回答

5

Python内置的map函数类似于Haskell的zipWith函数:

>>> def add(x,y): return x + y
... 
>>> map(add,[1,2,3],[10,20,30])
[11, 22, 33]

1
map是内置的,不需要在库中定义? - Thomas M. DuBuisson
1
我猜我希望能够解释为什么它(必须)被构建进去。 - Thomas M. DuBuisson
2
历史原因:map函数是内置函数已经存在很长时间了,至少可以追溯到90年代中期的1.x版本。而functoolsitertools则是较新的添加,反映了通过标准库中的单独模块和包添加功能的较新哲学。 - Ned Deily

2

0

这段 Python 代码类似于您提供的 zipWith' 函数:

def zip_with(f, l1, l2):
    if len(l1) == 0 or len(l2) == 0:
        return []
    else:
        return [f(l1[0], l2[0])] + zip_with(f, l1[1:], l2[1:])

这个函数与 Haskell 函数相比有一些缺点。首先,它看起来不太好看,因为 Python 没有模式匹配语法;我们必须使用 len[0][1:]。其次,Python 函数没有以任何方式使用惰性求值,所以 zip_with 将始终遍历整个列表,即使它可以提前停止。第三个问题是,这个函数对于结果列表中的每个元素都会调用自身一次,而 Python 的递归限制大约(或者确切地说?)是 1,000,因此如果输出列表超过约 1,000 个元素,这个函数将引发异常。

第二个和第三个问题可以使用生成器来解决。


你也可以使用 [f(l1.pop(),l2.pop())] + zip_with(f, l1, l2),因此不需要使用丑陋的 [0][1:] - assembly_wizard

0

这是一个很好的使用内置zip函数和列表推导式的候选方案:

>>> zip_with = lambda fn, la, lb: [fn(a, b) for (a, b) in zip(la, lb)]

>>> add2 = lambda x,y: x+y
>>> zip_with(add2, range(10), range(1,11))
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接