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

时间:2013-02-10 04:19:50

标签: python haskell

书籍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库,并设法使用它来复制这些函数的行为。

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()在此处是否有用。

4 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:2)

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

答案 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个元素,这个函数将引发异常

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

答案 3 :(得分: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]