5

次の 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

圏論または数学の他の分野に根ざした答えを探しています。

4

1 に答える 1