如果我想更改函數中參數的順序,該怎麼辦?如何更改參數的順序?
有flip
:
flip :: (a -> b -> c) -> b -> a -> c
,但我不明白如何使它爲參數的數量較多的工作。有沒有一種通用的方法來排列論據?
如果我想更改函數中參數的順序,該怎麼辦?如何更改參數的順序?
有flip
:
flip :: (a -> b -> c) -> b -> a -> c
,但我不明白如何使它爲參數的數量較多的工作。有沒有一種通用的方法來排列論據?
一般而言,最好的方法就是手動完成。假設你有一個函數
f :: Arg1 -> Arg2 -> Arg3 -> Arg4 -> Res
願與您
g :: Arg4 -> Arg1 -> Arg3 -> Arg2 -> Res
那麼你就寫
g x4 x1 x3 x2 = f x1 x2 x3 x4
如果你需要一個特定的排列幾次,那麼你當然可以從中抽象,如flip
對於雙參數的情況:
myflip :: (a4 -> a1 -> a3 -> a2 -> r) -> a1 -> a2 -> a3 -> a4 -> r
myflip f x4 x1 x3 x2 = f x1 x2 x3 x4
我認爲這是最好的方式來做到這一點,如果你需要對參數進行專門的重新排列,最容易定義你自己的函數來做到這一點,但我懷疑其中任何一個都可以用flip的組合來生成,而lambda就像(\ x - > flip $ fx),該函數部分應用該函數來翻轉除第一個和第二個之外的參數。 –
如果你喜歡的編輯功能,他們寫完後,你真的應該讀 Conal Elliott的優秀博客文章語義編輯組合子
http://conal.net/blog/posts/semantic-editor-combinators
其實,每個人都應該反正閱讀。這是一個真正有用的 方法(我在這裏濫用)。 Conal使用更多的構造,而不僅僅是result
和flip
以非常靈活的效果。
result :: (b -> b') -> ((a -> b) -> (a -> b'))
result = (.)
假設我有一個使用3個參數
use3 :: Char -> Double -> Int -> String
use3 c d i = c: show (d^i)
,我想掉前兩個,我只是用flip use3
像你說的, 功能,但如果我想交換第二個和第三個,我想要的是將flip
應用到use3
到它的第一個參數的結果。
use3' :: Char -> Int -> Double -> String
use3' = (result) flip use3
讓我們一起移動和交換的功能use5
使用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
我們需要申請flip
施加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
...這就是你應該停下來的地方,如果你喜歡簡單和優雅。 請注意,類型other
可能是b -> c -> d
,因爲神話般的庫裏和->
, , 的右關聯性,swap_2_3適用於一個函數,它可以接受任意數量的上面兩個參數。 對於任何更復雜的情況,您應該手動編寫一個置換函數。下面的內容僅僅是爲了知識的好奇。
現在,交換第二個和第四個參數怎麼辦? [旁白:有一個定理,我從任何排列可製成交換相鄰項的組成我的代數講座 記得了。]
我們可以做這樣的: 第1步:移動2旁邊4( 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
交換4回至位置2:
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搬過來1〜4,交換,移動5回從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
或者,如果你願意,你可以通過在翻轉重用swap_2_4
結束 (用2交換1和用4交換5),swap_2_4然後再翻轉兩端。
swap_1_5' = swap_1_2.swap_4_5. swap_2_4 .swap_4_5.swap_1_2
當然它更容易界定
swap_1_5'' f a b c d e = f e b c d a
它有明確的是,consise,高效的優點,並在ghci中沒有明確標註是一個有用的類型簽名。
但是,這是一個非常有趣的問題,謝謝。
@phimuemue它可能不是一個函數,但TH宏。是的,這樣的宏可以寫成,但簡單的lambda幾乎一樣短。 – permeakra
如果您傾向於有很多參數,則可能錯過創建適當數據類型的機會。或者你只是一個喋喋不休的人。 – Landei