5

『 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

私が今やりたいことの1つは、同じ本の章から、次のような、より興味深い高階関数のいくつかを複製できるかどうかを確認することです。

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

partial()ただし、これを行う方法がわかりません。また、ここで役立つかどうかもわかりません。

4

4 に答える 4

5

Pythonの組み込みmap関数は、Haskellのように動作しzipWithます。

>>> def add(x,y): return x + y
... 
>>> map(add,[1,2,3],[10,20,30])
[11, 22, 33]
于 2013-02-10T04:34:36.727 に答える
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

于 2013-02-10T04:35:12.893 に答える
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]
于 2013-02-10T09:30:50.007 に答える
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 関数と比較すると、この関数にはいくつかの欠点があります。1 つ目は、Python にはパターン マッチング構文がないため、見栄えがよくないことです。len[0]、および を[1:]代わりに使用する必要があります。2 つ目は、Python 関数は遅延評価をまったく使用しないため、zip_with早期に停止できたとしても、常にリスト全体を処理することです。3 つ目は、この関数は結果リストのすべての要素に対して 1 回自分自身を呼び出し、Python の再帰制限は約 (または正確に?) 1,000 であるため、出力リストが約 1,000 要素を超える場合、この関数は例外を発生させます。 .

2 番目と 3 番目の問題は、代わりにジェネレーターを使用して解決できます。

于 2013-02-10T07:33:43.350 に答える