如何在Go语言中进行柯里化?

huangapple go评论177阅读模式
英文:

How can go-lang curry?

问题

在函数式编程中,比如Haskell,我可以定义一个函数:

  1. add a b = a + b

然后 add 3 将返回一个接受一个参数并返回 3 + something 的函数。

在GO语言中,我该如何做到这一点?

当我定义一个接受多个(比如n个)参数的函数时,我能否只给它一个参数,并得到另一个接受 n-1 个参数的函数?

更新

对于我原始问题中不准确的措辞,我表示抱歉。

我认为我的问题应该分为两个问题:

  • GO语言中是否支持部分应用?
  • GO语言如何进行函数柯里化?

感谢TheOnly92和Alex解答了我的第二个问题。然而,我也对第一个问题很好奇。

英文:

In functional programming likes Haskell, I can define function

  1. add a b = a+b

Then add 3 will return a function that take one parameter and will return 3 + something

How can I do this in GO?

When I define a function that take more than one (say n) parameters, can I only give it one parameter and get another function that take n-1 parameters?

Update:

Sorry for the imprecise words in my original question.

I think my question should be asked as two qeustions:

  • Is there partial application in GO?
  • How GO do function curry?

Thanks TheOnly92 and Alex for solving my second question. However, I am also curious about the first question.

答案1

得分: 32

也许可以这样写:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func mkAdd(a int) func(int) int {
  6. return func(b int) int {
  7. return a + b
  8. }
  9. }
  10. func main() {
  11. add2 := mkAdd(2)
  12. add3 := mkAdd(3)
  13. fmt.Println(add2(5), add3(6))
  14. }
英文:

Perhaps something like

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func mkAdd(a int) func(int) int {
  6. return func(b int) int {
  7. return a + b
  8. }
  9. }
  10. func main() {
  11. add2 := mkAdd(2)
  12. add3 := mkAdd(3)
  13. fmt.Println(add2(5), add3(6))
  14. }

答案2

得分: 32

扩展上一个答案,允许您接受任意数量的参数:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func mkAdd(a int) func(...int) int {
  6. return func(b... int) int {
  7. for _, i := range b {
  8. a += i
  9. }
  10. return a
  11. }
  12. }
  13. func main() {
  14. add2 := mkAdd(2)
  15. add3 := mkAdd(3)
  16. fmt.Println(add2(5,3), add3(6))
  17. }

要翻译的代码已经翻译完成。

英文:

To extend on the previous answer, which allows you to take an arbitrary number of arguments:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func mkAdd(a int) func(...int) int {
  6. return func(b... int) int {
  7. for _, i := range b {
  8. a += i
  9. }
  10. return a
  11. }
  12. }
  13. func main() {
  14. add2 := mkAdd(2)
  15. add3 := mkAdd(3)
  16. fmt.Println(add2(5,3), add3(6))
  17. }

答案3

得分: 7

你可以进一步定义一个函数类型,并为其添加一个方法。

  1. package main
  2. import "fmt"
  3. type Add func(int, int) int
  4. func (f Add) Apply(i int) func(int) int {
  5. return func(j int) int {
  6. return f(i, j)
  7. }
  8. }
  9. func main() {
  10. var add Add = func(i, j int) int { return i + j }
  11. add3 := add.Apply(3)
  12. fmt.Println("add 3 to 2:", add3(2))
  13. }

你甚至可以尝试使用可变参数函数:

  1. package main
  2. import "fmt"
  3. type Multiply func(...int) int
  4. func (f Multiply) Apply(i int) func(...int) int {
  5. return func(values ...int) int {
  6. values = append([]int{i}, values...)
  7. return f(values...)
  8. }
  9. }
  10. func main() {
  11. var multiply Multiply = func(values ...int) int {
  12. var total int = 1
  13. for _, value := range values {
  14. total *= value
  15. }
  16. return total
  17. }
  18. var times2 Multiply = multiply.Apply(2)
  19. fmt.Println("times 2:", times2(3, 4), "(expect 24)")
  20. // ... and you can even cascade (if assigned the Multiply type)
  21. times6 := times2.Apply(3)
  22. fmt.Println("times 6:", times6(2, 3, 5, 10), "(expect 1800)")
  23. }

希望对你有所帮助!

英文:

You can take it a step further by defining a function type and then adding a method to it.

  1. package main
  2. import "fmt"
  3. type Add func(int, int) int
  4. func (f Add) Apply(i int) func(int) int {
  5. return func(j int) int {
  6. return f(i, j)
  7. }
  8. }
  9. func main() {
  10. var add Add = func(i, j int) int { return i + j }
  11. add3 := add.Apply(3)
  12. fmt.Println("add 3 to 2:", add3(2))
  13. }

You can even try with variadic functions:

  1. package main
  2. import "fmt"
  3. type Multiply func(...int) int
  4. func (f Multiply) Apply(i int) func(...int) int {
  5. return func(values ...int) int {
  6. values = append([]int{i}, values...)
  7. return f(values...)
  8. }
  9. }
  10. func main() {
  11. var multiply Multiply = func(values ...int) int {
  12. var total int = 1
  13. for _, value := range values {
  14. total *= value
  15. }
  16. return total
  17. }
  18. var times2 Multiply = multiply.Apply(2)
  19. fmt.Println("times 2:", times2(3, 4), "(expect 24)")
  20. // ... and you can even cascade (if assigned the Multiply type)
  21. times6 := times2.Apply(3)
  22. fmt.Println("times 6:", times6(2, 3, 5, 10), "(expect 1800)")
  23. }

Hope this helps!

huangapple
  • 本文由 发表于 2013年10月16日 11:45:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/19394868.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定