8

次のようなラムダ式を再利用し続けます

\x -> (f x, g x)

ここで、同じ入力を2つの関数に適用し、結果をペアでカプセル化します。これをキャプチャする関数を書くことができます

combine :: (a -> b) -> (a -> c) -> a -> (b,c)
combine f g x = (f x, g x)

これで、上記のラムダ式はちょうどcombine f gです。2つの質問があります。

  1. 私が見つけられない、これを行う標準ライブラリ関数があるかどうか知りたいです。
  2. 好奇心から、この関数をポイントフリー形式で書き直したいのですが、大変困っています。
4

3 に答える 3

12
  1. Control.Arrowこのための機能があります(&&&)。これは「より一般的な」タイプであり、残念ながらHoogleがそれを見つけられないことを意味します(おそらくこれはHoogleのバグと見なされるべきですか?)。

  2. あなたは通常、プラグインとして持っている、pointfreeでこの種のことを自動的に理解することができます。lambdabot#haskell

例えば:

<shachaf> @pl combine f g x = (f x, g x)
<lambdabot> combine = liftM2 (,)

ここliftM2で、の(r ->)インスタンスMonadはタイプを持っています(a -> b -> c) -> (r -> a) -> (r -> b) -> r -> c。もちろん、許可するプリミティブに応じて、このポイントフリーを作成する方法は他にもたくさんあります。

于 2013-01-16T03:28:05.533 に答える
12

私が見つけられない、これを行う標準ライブラリ関数があるかどうか知りたいです。

型クラスのために見逃しがちですが、を見てくださいControl.Arrow。プレーンArrowはカレーや塗布ができないので、Arrow必然的にコンビネータは無意味です。あなたがそれらを専門にしているなら(->)、あなたはあなたが望むものがこれであることがわかるでしょう:

(&&&) :: (Arrow a) => a b c -> a b c' -> a b (c, c')

の同等の操作など、他にも同様の機能があります。これは、Either(->)のようになります。

(|||) :: (a -> c) -> (b -> c) -> Either a b -> c

これはと同じeitherです。

好奇心から、この関数をポイントフリー形式で書き直したいのですが、大変困っています。

入力を複製しているので、ポイントフリーでそれを行うための何らかの方法が必要です。最も一般的な方法は、たとえば、またはApplicativeインスタンスMonadを使用することです。これは本質的に暗黙のインラインモナドであり、分割される引数は「環境」値です。このアプローチを使用すると、、、またはになり、になり、Sコンビネータになります。(->)\f g -> (,) <$> f <*> gReaderjoin f xf x xpurereturnconstfmap(.)(<*>) \f g x -> f x (g x)

于 2013-01-16T03:31:14.350 に答える
6

これを行うには、実際にはかなりの数の方法があります。最も一般的な方法は、次の(&&&)関数を使用することControl.Arrowです。

f &&& g

ただし、多くの場合、より多くの関数があるか、結果を別の関数に渡す必要があります。その場合は、アプリケーションスタイルを使用する方がはるかに便利です。それで

uncurry (+) . (f &&& g)

になります

liftA2 (+) f g

前述のように、これは複数の関数で使用できます。

liftA3 zip3 f g h
于 2013-01-16T04:01:27.987 に答える