異なる関数を2つの値にマップしてそれらを結合する関数を作成する必要がある場合があります。どのようにラムダを使用せずにそれを行うには?haskellのすべての引数に関数を適用する
私の機能は次のとおりです。
f :: a -> b
g :: c -> d
combine :: b -> d -> e
質問は:ラムダを使用せずに\x y -> combine (f x) (g y)
を記述する方法?
異なる関数を2つの値にマップしてそれらを結合する関数を作成する必要がある場合があります。どのようにラムダを使用せずにそれを行うには?haskellのすべての引数に関数を適用する
私の機能は次のとおりです。
f :: a -> b
g :: c -> d
combine :: b -> d -> e
質問は:ラムダを使用せずに\x y -> combine (f x) (g y)
を記述する方法?
代替pointfreeのスペルが(Data.Bifunctor
から)curry
、uncurry
のいずれか(***)
(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バージョンよりも短くてすむ。
f = g
の場合はData.Function
にon
を使用できます。それ以外の場合は、base
にはコンビネータはありません。適切なタイプの積み重ねを検索すると、concatenative
からbiSp
が明らかになる。
biSp :: (a -> c) -> (b -> d) -> (c -> d -> e) -> a -> b -> e
ただし、それがそのパッケージから使用する唯一の機能であれば、それだけでパッケージに依存したくないかもしれません。
それ以外の場合は、少なくともわずかに短いが実際にはより読みにくいものを使用できます。
(. g) . combine . f
またはprofunctors
からData.Profunctor
でdimap
を使用。これには別のパッケージが必要ですが、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
を書いてください。