2016-11-12 10 views
2

異なる関数を2つの値にマップしてそれらを結合する関数を作成する必要がある場合があります。どのようにラムダを使用せずにそれを行うには?haskellのすべての引数に関数を適用する

私の機能は次のとおりです。

f :: a -> b 
g :: c -> d 
combine :: b -> d -> e 

質問は:ラムダを使用せずに\x y -> combine (f x) (g y)を記述する方法?

答えて

4

代替pointfreeのスペルが(Data.Bifunctorから)curryuncurryのいずれか(***)Control.Arrowから)またはbimapを使用してペアとして引数を扱う含まれます

GHCi> :t \combine f g -> curry (uncurry combine . (f *** g)) 
\combine f g -> curry (uncurry combine . (f *** g)) 
    :: (a1 -> b1 -> c) -> (a -> a1) -> (b -> b1) -> a -> b -> c 

なおし、jpathの提案とは異なり、このISN non-pointfreeバージョンよりも短くてすむ。

7

f = gの場合はData.Functiononを使用できます。それ以外の場合は、baseにはコンビネータはありません。適切なタイプの積み重ねを検索すると、concatenativeからbiSpが明らかになる。

biSp :: (a -> c) -> (b -> d) -> (c -> d -> e) -> a -> b -> e 

ただし、それがそのパッケージから使用する唯一の機能であれば、それだけでパッケージに依存したくないかもしれません。

それ以外の場合は、少なくともわずかに短いが実際にはより読みにくいものを使用できます。

(. g) . combine . f 

またはprofunctorsからData.Profunctordimapを使用。これには別のパッケージが必要ですが、lensまたはlensに応じてパッケージを使用しているため、すでに間接的にprofunctorsに依存している可能性があります。

dimap f (. g) combine 

これは、3つの引数に簡単に拡張できます。以下はすべて同じで、最短のものから最も構造化されたものまで注文されています。最後の2つでは、それらを任意の数の引数に拡張することが特に簡単です。

dimap f (dimap g (. h)) combine3 
(dimap f . dimap g) (. h) combine3 
(dimap f . dimap g . dimap h) id combine3 

dimapが何をしているのだろうか。これは素晴らしいチュートリアルです:I love profunctors. They're so easy.

またはbiSpを書いてください。

関連する問題