15

さまざまな折りたたみ関数を使用して、タプルのリストを 1 つのタプルに折りたたみたい場合があります。たとえば、runState の結果のリストを結合するために、(ある意味で) 結合された状態と結合された結果を取得します。

次の実装を検討してください。

wish :: (a -> a' -> a) -> (b -> b' -> b) -> (a,b) -> [(a', b')] -> (a,b)
wish lfn rfn x xs = foldl (\(a,b) -> (lfn a) *** (rfn b)) x xs

動作しますが、このラムダには違和感があります。lfn *** rfnそれ自体は の型を持って(a,b) -> (a -> a', b -> b')いますが、パターン マッチングに頼らずにタプルに適切に適用する方法を見つけることができません。私が見逃している明確でエレガントな方法はありますか? それは、タイプのライブラリ関数(a,a') -> (a -> a, a' -> a') -> (a, a')またはまったく異なるアプローチである可能性があります。

4

1 に答える 1

9

Control.Arrowアリティの高い関数にはあまり注意を払いません。本当に必要なのは、アリティ 2foo :: (a -> a' -> a'') -> (b -> b' -> b'') -> (a,b) -> (a',b') -> (a'',b'')の for functions の類似物で(***)ある function です。Data.Biapplicative (パッケージ bifunctor から) にそのような関数があり、やや一般的な署名がありbiliftA2 :: Biapplicative w => (a -> b -> c) -> (d -> e -> f) -> w a d -> w b e -> w c fます。2 要素タプルには Biapplicative インスタンスがあるため、必要なのはそれだけです。

あなたのコードに対して私が見ることができる唯一の不満は、ラムダのカリー化が自明ではないということです。私はより明示的な方が好きかもしれません\(a,b) (a',b') -> (lfn a a', rfn b b')

編集メモ: 必要な関数が存在しないと結論付け、それを定義することを提案しました。Carl のコメントに刺激されて、私は Biapplicative にあるものを見つけました (より一般的な型シグネチャにより、Hoogle は私の提案したシグネチャの下でそれを見つけることができませんでした)。

于 2013-05-21T18:52:15.803 に答える