2012-08-26 13 views
18

関数の引数の順序を変更したいのですが?引数の順序を変更する方法は?

flip :: (a -> b -> c) -> b -> a -> c 

が、私はそれが引数のより多くのために働くようにする方法が表示されない:

ありflipです。引数を並べ替える一般的な方法はありますか?

+0

@phimuemueこれは機能ではなく、THマクロである可能性があります。はい、そのようなマクロを書くことができますが、単純なラムダはほぼ同じくらい短いです。 – permeakra

+5

多くの議論がある傾向がある場合は、適切なデータ型を作成する機会がなくなる可能性があります。それとも、あなたは単調な人です。 – Landei

答えて

12

一般的には、手動で行うのが最も良い方法です。あなたが機能

f :: Arg1 -> Arg2 -> Arg3 -> Arg4 -> Res 

を持っていると仮定して、あなたが特定の順列を複数回必要な場合

g :: Arg4 -> Arg1 -> Arg3 -> Arg2 -> Res 

が、あなたは、あなたがそれから、もちろん抽象することができ、

g x4 x1 x3 x2 = f x1 x2 x3 x4 

を書きたいと思いますたとえば、flipのように2つの引数の場合は、

myflip :: (a4 -> a1 -> a3 -> a2 -> r) -> a1 -> a2 -> a3 -> a4 -> r 
myflip f x4 x1 x3 x2 = f x1 x2 x3 x4 
あなたは、彼らが書かれている後の編集機能のように感じる場合は
+2

私はこれを行う最良の方法だと思います。特殊な再構成が必要な場合は、独自の関数を定義するのが最も簡単ですが、これらはフリップの構成で生成でき、 x - > flip $ fx)は、部分的に関数を適用して、1番目と2番目以外の引数を反転させます。 –

32

、あなたが本当に Conalエリオットの優れたブログ記事セマンティックエディタコンビネータ実際に

http://conal.net/blog/posts/semantic-editor-combinators

をお読みください、誰もがとにかくそれをお読みください。これは本当に便利な メソッドです(私はここで悪用しています)。 Conalは、resultflipよりも多くの構造を非常に柔軟な効果で使用します。

result :: (b -> b') -> ((a -> b) -> (a -> b')) 
result = (.) 

私がしたい場合は、私は3つの引数

use3 :: Char -> Double -> Int -> String 
use3 c d i = c: show (d^i) 

を使用して、私は最初の二つを交換したい機能を持って、私はちょうどあなたが言うように、flip use3を使用 が、したいと仮定2番目と3番目のスワップは、私が望むのは、use3を最初の引数に適用した結果にflip を適用することです。

use3' :: Char -> Int -> Double -> String 
use3' = (result) flip use3 

のに沿って移動し、我々はそれ三つの引数、 最初だしuse5を適用した結果にflipを適用する必要がある5.

use5 :: Char -> Double -> Int -> (Int,Char) -> String  -> String 
use5' :: Char -> Double -> Int -> String  -> (Int,Char) -> String 

use5 c d i (n,c') s = c : show (d^i) ++ replicate n c' ++ s 

を使用する関数use5の第四及び第五引数を交換してみましょう結果は次のようになります。

use5' = (result.result.result) flip use5 

なぜ後で考えて保存しないのですか定義します。

swap_1_2 :: (a1 -> a2 -> other) -> (a2 -> a1 -> other) 
swap_2_3 :: (a1 -> a2 -> a3 -> other) -> (a1 -> a3 -> a2 -> other) 
--skip a few type signatures and daydream about scrap-your-boilerplate and Template Haskell  

swap_1_2 = flip  
swap_2_3 = result flip 
swap_3_4 = (result.result) flip 
swap_4_5 = (result.result.result) flip 
swap_5_6 = (result.result.result.result) flip 

...シンプルさとエレガンスが好きな人は、ここで停止する必要があります。 タイプotherb -> c -> dになる可能性があります。カレーと右の結合性が->であるため、 swap_2_3は2つ以上の引数を取る関数に対して機能します。 もっと複雑なことは、実際に置換された関数を手で書くべきです。 以下は、知的好奇心のためのものです。

ここで、2番目と4番目の引数を入れ替えるのはどうですか? は[脇:私はすべての順列は、隣接するアイテムを交換する構成とすることができる私の代数の講義 から覚えている定理があります。]

は、我々はこのようにそれを行うことができます: 手順1:4の次の動き2( swap_2_3

a1 -> a2 -> a3 -> a4 -> otherstuff 
a1 -> a3 -> a2 -> a4 -> otherstuff 

swap_3_4

a1 -> a3 -> a2 -> a4 -> otherstuff 
a1 -> a3 -> a4 -> a2 -> otherstuff 

を使用して交換再度swap_2_3を使用して位置2に戻って4スワップ:

a1 -> a3 -> a4 -> a2 -> otherstuff 
a1 -> a4 -> a3 -> a2 -> otherstuff 

ので

swap_2_4 = swap_2_3.swap_3_4.swap_2_3 

は、たぶんそこに結果 の多くを直接そこに取得するより簡潔な方法ですし、反転したが、ランダムなメッシングは私のためにそれを見つけられませんでした!

同様に、1交換すると5我々は、5で、4にオーバースワップを1を移動する4から1

swap_1_5 = swap_1_2.swap_2_3.swap_3_4 . swap_4_5 . swap_3_4.swap_2_3.swap_1_2 

に戻って5を移動したり、お好みであれば、あなたがでひっくり返すことでswap_2_4を再利用することができことができます (2と5を4で置き換える)swap_2_4を最後にもう一度フリップします。もちろん

swap_1_5' = swap_1_2.swap_4_5. swap_2_4 .swap_4_5.swap_1_2 

それは、明確に、consiseであるという利点を持って効率的かつ明示的に注釈を付けることなく、GHCiのに役立つ型シグネチャを持つ

swap_1_5'' f a b c d e = f e b c d a 

を定義することがずっと簡単です。

しかし、これは非常に面白い質問でした。

関連する問題