Dan*_*uck 4 python haskell functional-programming combinators
在Haskell中,我会写:
main = do mapM_ print . map (\x -> x^2) . filter (\x -> (mod x 2) == 0) $ [1..20]
Run Code Online (Sandbox Code Playgroud)
在Python我将不得不为使用许多括号或无用的变量...有像什么.,并$在Python?
(我不熟悉Haskell,但如果我正确理解你的代码片段......)
您可以使用列表推导来执行过滤和取幂.
[i**2 for i in range(1,21) if i%2 == 0]
Run Code Online (Sandbox Code Playgroud)
我会使用任何可用的惯用 Python 工具,例如列表推导式,正如其他人指出的那样,而不是试图假装您正在编写 Haskell,但如果您真的必须,您compose甚至可以在 Python 中使用组合器函数:
# this is essentially just foldr (or right `reduce`) specialised on `compose2`
def compose(*args):
ret = identity
for f in reversed(args):
ret = compose2(f, ret)
return ret
def identity(x): return x
def compose2(f, g): return lambda x: f(g(x))
Run Code Online (Sandbox Code Playgroud)
你可以这样使用:
from functools import partial
# equiv. of: map (\x -> x^2) . filter (\x -> (mod x 2) == 0) $ [1..20]
compose(partial(map, lambda x: x**2), partial(filter, lambda x: x % 2 == 0))(range(1, 21))
Run Code Online (Sandbox Code Playgroud)
无可否认,它确实有效:
>>> compose(partial(map, lambda x: x**2), partial(filter, lambda x: x % 2 == 0))(range(1, 21))
[4, 16, 36, 64, 100, 144, 196, 256, 324, 400]
Run Code Online (Sandbox Code Playgroud)
...但是正如您所看到的,Python 缺少某些概念,例如柯里化和可任意定义的中缀运算符,因此即使在语义上,上述代码片段与 Haskell 代码片段等效(甚至相同),但它读起来非常糟糕。
至于$运算符:它在 Python 中几乎没有相关性——它在 Haskell 中的主要目的与运算符优先级有关,这在 Python 中不是问题,因为无论如何你在大多数时间都不能真正使用运算符,并且所有构建的-in 运算符具有预定义的优先级。
而$在 Haskell 中还可以用作高阶函数:
zipWith ($) [(3*), (4+), (5-)] [1,2,3]
Run Code Online (Sandbox Code Playgroud)
...在 Python 中使用它的(已弃用的)apply“组合器”复制它,将再次导致代码丑陋:
>>> list(starmap(apply, zip([lambda x: 3 * x, lambda x: 4 + x, lambda x: 5 - x], map(lambda x: [x], [1, 2, 3]))))
[3, 6, 2]
Run Code Online (Sandbox Code Playgroud)
——同样,Python 的几个基本限制在这里发挥作用:
list(),就不会返回“正常”列表;(a -> b) -> a -> bbut (a1 -> a2 -> ... -> aN -> b) -> (a1, a2, ..., aN) -> b,所以你需要用[]和 use starmapnot the normal包裹列表元素map;这也是没有柯里化的结果;map、reduce等;