如果我想改变函数参数的顺序怎么办?
有一个flip
函数可以使用:
flip :: (a -> b -> c) -> b -> a -> c
但是我不知道如何使其适用于更多的参数。是否有一种通用方法可以排列参数?
如果我想改变函数参数的顺序怎么办?
有一个flip
函数可以使用:
flip :: (a -> b -> c) -> b -> a -> c
但是我不知道如何使其适用于更多的参数。是否有一种通用方法可以排列参数?
http://conal.net/blog/posts/semantic-editor-combinators
实际上,无论如何每个人都应该阅读它。这是一种真正有用的方法(我在这里滥用了它)。Conal使用比仅仅result
和flip
更多的结构来达到非常灵活的效果。result :: (b -> b') -> ((a -> b) -> (a -> b'))
result = (.)
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
的第四个和第五个参数。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
的结果应用flip
,这样就得到了结果的结果的结果: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
,因此由于神奇的Curry和->
的右结合性,
swap_2_3适用于接受两个以上参数的函数。
对于更复杂的情况,您确实应该手动编写一个排列函数。
接下来只是为了满足知识好奇心。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
so
swap_2_4 = swap_2_3.swap_3_4.swap_2_3
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
,然后再次在两端翻转。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
通常最好的方法是手动完成。假设您有一个函数
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