2013-02-10 77 views
5

从书中Learn You a Haskell For Great Good偏函数的相关章节包含以下代码:什么是这些Haskell高阶函数的Python等价物?

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

您应该编辑和修复你的职责,确保他们都是语法正确。例如,你的第一个问题就是缺少它的论点。 – 2013-02-10 04:34:51

+2

从技术上讲,你必须在任何转换中使用'partial',因为所有的Haskell函数都会自动执行curried,而'partial'模拟curried函数必须部分应用的能力。或者您可以将python版本编写为curried函数,但是您必须将它们称为“foo(a)(b)(c)'。 – Wes 2013-02-10 04:57:33

+2

小调:你想要“部分应用功能”而不是“部分功能”。 – 2013-02-10 09:35:21

回答

5

Python的内置map功能的行为就像Haskell的zipWith

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

地图是内置的而不是在库中定义的? – 2013-02-10 04:36:17

+0

是的,地图和添加内置于Python中的函数 – 2013-02-10 04:53:57

+1

我想我希望解释为什么它是(必须是?)内置的。 – 2013-02-10 05:28:56

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函数不会以任何方式使用懒惰评估,所以即使它可能早早停止,它也会一直遍历整个列表。第三个是该函数为结果列表的每个元素调用一次,并且Python的递归限制约为1000(或者恰好?)1,000,所以如果输出列表长度大于1,000个元素,此函数将引发异常。

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

+0

你也可以使用'[f(l1.pop(),l2。pop())] + zip_with(f,l1,l2)''因此不需要丑陋的'[0]'或'[1:]' – ThatWeirdo 2016-11-13 20:07:11

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] 
相关问题