次の Haskell コードを検討してください。
countWhere :: (a -> Bool) -> [a] -> Int
countWhere predicate xs = length . filter predicate $ xs
JavaScript では、これは次のように記述されます。
function countWhere(predicate, xs) {
return xs.filter(predicate).length;
}
ご覧のとおり、関数の合成は、JavaScript のメソッドの連鎖に非常に似ています。メソッドのチェーンが左から右に読み取られる方法が非常に気に入っています。Haskell では、次のように>>>function fromControl.Arrowと reverse function application を使用して同様のことを行うことができます。
import Control.Arrow
($>) :: a -> (a -> b) -> b
($>) = flip ($)
countWhere :: (a -> Bool) -> [a] -> Int
countWhere predicate xs = xs $> filter predicate >>> length
この関数をポイントフリースタイルで書きたいと思います。関数合成を使用して、次のように記述します。
(.:) :: (b -> c) -> (d -> a -> b) -> d -> a -> c
(.:) = (.) (.) (.)
countWhere :: (a -> Bool) -> [a] -> Int
countWhere = length .: filter
ただし、次のように逆関数合成を使用して、この関数をポイントフリースタイルで記述したいと思います。
(.:) :: (b -> c) -> (d -> a -> b) -> d -> a -> c
(.:) = (.) (.) (.)
(:.) :: (d -> a -> b) -> (b -> c) -> d -> a -> c
(:.) = flip (.:)
countWhere :: (a -> Bool) -> [a] -> Int
countWhere = filter :. length
私の不満は:.、逆の関数構成ではなく、関数構成の観点から関数を定義する必要があることです。あれは:
(:.) = flip $ (.) (.) (.)
-- instead of
(:.) = (>>>) (>>>) (>>>)
もちろん(>>>) (>>>) (>>>)型違いです。それは私が探している機能ではありません。
関数合成の優れた点は、上で示したように、それ自体で合成して「高次関数合成」を形成できることです。したがって、その型シグネチャは直観的に後方ですが、実際には前方f . g = \x -> f (g x)ですf . g = \x -> g (f x)。
これは私の実際の質問につながります.対応する「高次関数合成」の>>>代わりに、逆関数合成(つまり)の観点から「高次逆関数合成」を定義する方法はありますか?flip
圏論または数学の他の分野に根ざした答えを探しています。