2012-03-04 6 views
3

私は適切な専門用語がないことを許してください - 私は変則性などについて何も知らないが、私が表現しようとしている概念がある種の言葉で記述できるという気持ちがある。map、reduce、またはfilterをとり、それらの関数化されたバージョンを返す関数を書くことは可能ですか?

地図、削減し、フィルタ、古典高階関数、すべての機能fとデータのリストを取りxsし、すべてのxsにそのfで何かをすることの一般的な構造を持っています。さて、それらのそれぞれについて、私は、機能しているバージョン - mapf、reducef、filterfと呼ぶ - を呼ぶことができます。代わりにデータの一部を取りますxと関数のリストfsfsのデータをx 。具体的には、mapfはf1(x), f2(x), ...のリストを返し、reducefはf3 (f2 (f1 (x)))またはf1 (f2 (f3 (x)))(左右かどうかによって異なる)を返し、filterfはそれぞれf1(x), f2(x), ...がtrueであったかどうかをテストしてfsだけを返します。

私の質問は次のとおりです。map、reduce、またはfilterを引数とし、対応するmapf、reducef、またはfilterf関数を生成する汎用関数functioniseを記述することは可能ですか? (もちろん、エレガントな方法では、一連のケース表現ではなく)。

どのようなプログラミング言語が使用されても構いません。私自身の実験では、私はHaskellのを使用して、どのようなこの質問に私を導いたことは、私は機能の3つのすべてが非常に同様の方法で定義することができることに気づいたということでしたされています:私はでtantalisedい

rev = \x y -> y x 

mapf :: a -> [a -> b] -> [b] 
mapf x fs = map (rev x) fs 

reducef :: a -> [a -> a] -> a 
reducef x fs = foldl rev x fs 

filterf :: a -> [a -> Bool] -> [a -> Bool] 
filterf x fs = filter (rev x) fs 

私はそれが可能であることを知り、それが不可能であることをどのように、あるいは見せるかを見て、理由を見たいと思います。私が言ったように、プログラミング言語は重要ではないので、言語Aでは可能だが言語BではタイプBシステムではないということは気にしない。興味深いだろう。

ありがとうございました!

答えて

3

のちょうど別の専門でありますwiki under pointfree

swing f c a = f ($ a) c 

swing map :: forall a b. [a -> b] -> a -> [b] 
swing any :: forall a. [a -> Bool] -> a -> Bool 
swing foldr :: forall a b. b -> a -> [a -> b -> b] -> b 
swing zipWith :: forall a b c. [a -> b -> c] -> a -> [b] -> [c] 
swing find :: forall a. [a -> Bool] -> a -> Maybe (a -> Bool) 

-- applies each of the predicates to the given value, returning the first 
-- predicate which succeeds, if any 

swing partition :: forall a. [a -> Bool] -> a -> ([a -> Bool], [a -> Bool]) 
5

reducefは非常に他のものと同じパターンに適合していませんが、mapfilterのために、パターンが\g x fs -> g (rev x) fs、略して(. rev)です:

> :t (. rev) map 
(. rev) map :: a -> [a -> t] -> [t] 
> :t (. rev) filter 
(. rev) filter :: a -> [a -> Bool] -> [a -> Bool] 

あなたがreducefを含めたい場合は、あなたの」それはでは動作しません

> :t ($ rev) foldl 
($ rev) foldl :: t -> [t -> t] -> t 

($ rev)に短縮することができ、わずかに異なるパターン、\g x fs -> g rev x fsを、必要とするでしょうと直接filter、しかし、あなたは(map .)(filter .)上でそれを使用することができます。

> :t ($ rev) (map .) 
($ rev) (map .) :: t1 -> [t1 -> t] -> [t] 
> :t ($ rev) (filter .) 
($ rev) (filter .) :: t1 -> [t1 -> Bool] -> [t1 -> Bool] 

だから私はfunctionalise = ($ rev)は、あなたが得ることができると同じくらい近いと思います。

16

あなたのアイデアを軽視するのは意味がありませんが、努力する価値はほとんどありません。値に関数のリストを適用するたとえば、次のようになります。

map ($ v) [f1, f2, f3] 

あなたmapfはあなたのコードは、私が中に隠された「スイング」に似ていますmap

mapf :: v -> [(v -> a)] -> [a] 
mapf v fs = map ($v) fs 
+2

同様に、 'filterf vs fs = filter($ v)fs' – rampion

関連する問題