这些Haskell higherorder函数的Python等价物是什么?

2024-10-03 15:26:38 发布

您现在位置:Python中文网/ 问答频道 /正文

Learn You a Haskell For Great Good中关于部分函数的章节包含以下代码:

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库,并成功地复制了使用它的函数的行为。在

^{pr2}$

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

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

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


Tags: 函数youforhaskelllearngoodletxs
3条回答

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

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

此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]、和{}。第二个原因是Python函数没有以任何方式使用lazy求值,因此zip_with将始终遍历整个列表,即使它可以通过提前停止来避免。第三种情况是,对于结果列表中的每个元素,这个函数都会调用自己一次,而Python的递归限制是大约(或者确切地说?)1000,因此如果输出列表的长度超过1000个元素,则此函数将引发异常。在

第二和第三个问题可以用发电机来解决。在

def add(a, b):
    return a + b

x = [1, 2, 3, 4]
y = [5, 6, 7, 8]

>> map(add, x, y)
[6, 8, 10, 12]

另外,请检查Python内置的itertools模块:http://docs.python.org/2/library/itertools.html

相关问题 更多 >