gpt4 book ai didi

haskell - 如何更改参数的顺序?

转载 作者:行者123 更新时间:2023-12-02 06:57:35 25 4
gpt4 key购买 nike

如果我想更改函数中参数的顺序怎么办?

翻转:

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

但我不知道如何让它适用于更多的参数。有没有通用的方法来排列参数?

最佳答案

如果您想在编写函数后对其进行编辑,您真的应该阅读Conal Elliott 的优秀博客文章语义编辑器组合

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 ,但如果我想交换第二个和第三个,我想要的是应用 flipuse3 应用于其第一个参数的结果。

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

让我们继续并交换使用 5 的函数 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

我们需要将 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,因此由于出色的 Curry 和 -> 的右关联性,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,我们可以将 1 移至 4,与 5 交换,将 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(将 1 与 2 交换,5 与 4 交换),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

其优点是清晰、简洁、高效,并且在 ghci 中具有有用的类型签名,无需显式注释。

但是,这是一个非常有趣的问题,谢谢。

关于haskell - 如何更改参数的顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12129029/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com