0xf

日記だよ

golangで簡単なカリー化

ジェネリクスあるのでコネコネしてみた。

たとえば int 二つをとる関数のカリー化関数は個別には簡単に書ける

func curry(f func(int, int) int, x int) func(int) int {
    return func(y int) int {
        return f(y, x)
    }
}

これを、ジェネリクスを使って

func curry[R, X, Y any](f func(X, Y) R, x X) func(Y) R {
    return func(y Y) R {
        return f(x, y)
    }
}

こう書くことはできる。リターンタイプが最初の型パラメータにするのは手癖です。

であれば

func curry1[R, X, Y any](f func(X, Y) R, x X) func(Y) R {
    return func(y Y) R {
        return f(x, y)
    }
}

func curry2[R, X, Y, Z any](f func(X, Y, Z) R, x X) func(Y, Z) R {
    return func(y Y, z Z) R {
        return f(x, y, z)
    }
}

// 変数名はミスっている
func curry3[R, X, Y, Z, Z1 any](f func(X, Y, Z, Z1) R, x X) func(Y, Z, Z1) R {
....

こういうふうに増やしていくことはできる。そんな、と思ったけどそういえばこういう型定義よく見る気はしますね。マクロで増やしたりするといいのか。

メソッドのレシーバに型パラメータは使えなさそう

func (f func(X, Y) R) curry[R, X, Y any](x X) func(Y) R {
    return func(y Y) R {
        return f(x, y)
    }
}

こういう書き方はできない。これができると便利なんだけどな。method must have no type parametersと言われてしまう。そもそもレシーバに型パラメータ付きの型も指定できない。むーん。