Created
November 27, 2021 00:13
-
-
Save luavixen/7d5a6b362378692b13738925168edbff to your computer and use it in GitHub Desktop.
Generic Haskell/functional style currying in Kotlin using extension functions. Example: https://pl.kotl.in/LuUAPZxOV
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const alphabet = 'abcdefghijklmnopqrstuvwxyz'.split(''); | |
const generateBindImpl = (leftCount, rightCount) => { | |
const totalCount = leftCount + rightCount; | |
const genericTypes = []; | |
for (let i = 0; i < totalCount; i++) { | |
genericTypes.push('A' + i); | |
} | |
const leftTypes = genericTypes.slice(0, leftCount); | |
const rightTypes = genericTypes.slice(leftCount); | |
const availableAlphabet = [...alphabet].reverse(); | |
const argumentNames = []; | |
const boundParameterDeclarations = []; | |
for (const genericType of leftTypes) { | |
const identifier = availableAlphabet.pop(); | |
argumentNames.push(identifier); | |
boundParameterDeclarations.push(`${identifier}: ${genericType}`); | |
} | |
const unboundParameterNames = []; | |
for (let i = 0; i < rightCount; i++) { | |
const identifier = availableAlphabet.pop(); | |
argumentNames.push(identifier); | |
unboundParameterNames.push(identifier); | |
} | |
const lines = [ | |
`operator fun <${[`T : (${genericTypes.join(', ')}) -> R`, `R`, ...genericTypes].join(', ')}> T.invoke(${boundParameterDeclarations.join(', ')}): (${rightTypes.join(', ')}) -> R {`, | |
` return { ${unboundParameterNames.join(', ')}${unboundParameterNames.length ? ' -> ' : ''}this(${argumentNames.join(', ')}) }`, | |
`}` | |
]; | |
return lines.join('\n'); | |
}; | |
const maxLeftCount = 5; | |
const maxRightCount = 5; | |
for (let x = 0; x <= maxLeftCount; x++) { | |
for (let y = 1; y <= maxRightCount; y++) { | |
console.log(generateBindImpl(x, y)); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
operator fun <T : (A0) -> R, R, A0> T.invoke(): (A0) -> R { | |
return { a -> this(a) } | |
} | |
operator fun <T : (A0, A1) -> R, R, A0, A1> T.invoke(): (A0, A1) -> R { | |
return { a, b -> this(a, b) } | |
} | |
operator fun <T : (A0, A1, A2) -> R, R, A0, A1, A2> T.invoke(): (A0, A1, A2) -> R { | |
return { a, b, c -> this(a, b, c) } | |
} | |
operator fun <T : (A0, A1, A2, A3) -> R, R, A0, A1, A2, A3> T.invoke(): (A0, A1, A2, A3) -> R { | |
return { a, b, c, d -> this(a, b, c, d) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4) -> R, R, A0, A1, A2, A3, A4> T.invoke(): (A0, A1, A2, A3, A4) -> R { | |
return { a, b, c, d, e -> this(a, b, c, d, e) } | |
} | |
operator fun <T : (A0, A1) -> R, R, A0, A1> T.invoke(a: A0): (A1) -> R { | |
return { b -> this(a, b) } | |
} | |
operator fun <T : (A0, A1, A2) -> R, R, A0, A1, A2> T.invoke(a: A0): (A1, A2) -> R { | |
return { b, c -> this(a, b, c) } | |
} | |
operator fun <T : (A0, A1, A2, A3) -> R, R, A0, A1, A2, A3> T.invoke(a: A0): (A1, A2, A3) -> R { | |
return { b, c, d -> this(a, b, c, d) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4) -> R, R, A0, A1, A2, A3, A4> T.invoke(a: A0): (A1, A2, A3, A4) -> R { | |
return { b, c, d, e -> this(a, b, c, d, e) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4, A5) -> R, R, A0, A1, A2, A3, A4, A5> T.invoke(a: A0): (A1, A2, A3, A4, A5) -> R { | |
return { b, c, d, e, f -> this(a, b, c, d, e, f) } | |
} | |
operator fun <T : (A0, A1, A2) -> R, R, A0, A1, A2> T.invoke(a: A0, b: A1): (A2) -> R { | |
return { c -> this(a, b, c) } | |
} | |
operator fun <T : (A0, A1, A2, A3) -> R, R, A0, A1, A2, A3> T.invoke(a: A0, b: A1): (A2, A3) -> R { | |
return { c, d -> this(a, b, c, d) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4) -> R, R, A0, A1, A2, A3, A4> T.invoke(a: A0, b: A1): (A2, A3, A4) -> R { | |
return { c, d, e -> this(a, b, c, d, e) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4, A5) -> R, R, A0, A1, A2, A3, A4, A5> T.invoke(a: A0, b: A1): (A2, A3, A4, A5) -> R { | |
return { c, d, e, f -> this(a, b, c, d, e, f) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4, A5, A6) -> R, R, A0, A1, A2, A3, A4, A5, A6> T.invoke(a: A0, b: A1): (A2, A3, A4, A5, A6) -> R { | |
return { c, d, e, f, g -> this(a, b, c, d, e, f, g) } | |
} | |
operator fun <T : (A0, A1, A2, A3) -> R, R, A0, A1, A2, A3> T.invoke(a: A0, b: A1, c: A2): (A3) -> R { | |
return { d -> this(a, b, c, d) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4) -> R, R, A0, A1, A2, A3, A4> T.invoke(a: A0, b: A1, c: A2): (A3, A4) -> R { | |
return { d, e -> this(a, b, c, d, e) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4, A5) -> R, R, A0, A1, A2, A3, A4, A5> T.invoke(a: A0, b: A1, c: A2): (A3, A4, A5) -> R { | |
return { d, e, f -> this(a, b, c, d, e, f) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4, A5, A6) -> R, R, A0, A1, A2, A3, A4, A5, A6> T.invoke(a: A0, b: A1, c: A2): (A3, A4, A5, A6) -> R { | |
return { d, e, f, g -> this(a, b, c, d, e, f, g) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4, A5, A6, A7) -> R, R, A0, A1, A2, A3, A4, A5, A6, A7> T.invoke(a: A0, b: A1, c: A2): (A3, A4, A5, A6, A7) -> R { | |
return { d, e, f, g, h -> this(a, b, c, d, e, f, g, h) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4) -> R, R, A0, A1, A2, A3, A4> T.invoke(a: A0, b: A1, c: A2, d: A3): (A4) -> R { | |
return { e -> this(a, b, c, d, e) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4, A5) -> R, R, A0, A1, A2, A3, A4, A5> T.invoke(a: A0, b: A1, c: A2, d: A3): (A4, A5) -> R { | |
return { e, f -> this(a, b, c, d, e, f) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4, A5, A6) -> R, R, A0, A1, A2, A3, A4, A5, A6> T.invoke(a: A0, b: A1, c: A2, d: A3): (A4, A5, A6) -> R { | |
return { e, f, g -> this(a, b, c, d, e, f, g) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4, A5, A6, A7) -> R, R, A0, A1, A2, A3, A4, A5, A6, A7> T.invoke(a: A0, b: A1, c: A2, d: A3): (A4, A5, A6, A7) -> R { | |
return { e, f, g, h -> this(a, b, c, d, e, f, g, h) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4, A5, A6, A7, A8) -> R, R, A0, A1, A2, A3, A4, A5, A6, A7, A8> T.invoke(a: A0, b: A1, c: A2, d: A3): (A4, A5, A6, A7, A8) -> R { | |
return { e, f, g, h, i -> this(a, b, c, d, e, f, g, h, i) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4, A5) -> R, R, A0, A1, A2, A3, A4, A5> T.invoke(a: A0, b: A1, c: A2, d: A3, e: A4): (A5) -> R { | |
return { f -> this(a, b, c, d, e, f) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4, A5, A6) -> R, R, A0, A1, A2, A3, A4, A5, A6> T.invoke(a: A0, b: A1, c: A2, d: A3, e: A4): (A5, A6) -> R { | |
return { f, g -> this(a, b, c, d, e, f, g) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4, A5, A6, A7) -> R, R, A0, A1, A2, A3, A4, A5, A6, A7> T.invoke(a: A0, b: A1, c: A2, d: A3, e: A4): (A5, A6, A7) -> R { | |
return { f, g, h -> this(a, b, c, d, e, f, g, h) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4, A5, A6, A7, A8) -> R, R, A0, A1, A2, A3, A4, A5, A6, A7, A8> T.invoke(a: A0, b: A1, c: A2, d: A3, e: A4): (A5, A6, A7, A8) -> R { | |
return { f, g, h, i -> this(a, b, c, d, e, f, g, h, i) } | |
} | |
operator fun <T : (A0, A1, A2, A3, A4, A5, A6, A7, A8, A9) -> R, R, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9> T.invoke(a: A0, b: A1, c: A2, d: A3, e: A4): (A5, A6, A7, A8, A9) -> R { | |
return { f, g, h, i, j -> this(a, b, c, d, e, f, g, h, i, j) } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Run this example: https://pl.kotl.in/LuUAPZxOV | |
val printFourThings: (Any, Any, Any, Any) -> Unit = { a, b, c, d -> | |
println("$a $b $c $d") | |
} | |
val curried1 = printFourThings(1, 2) | |
val curried2 = curried1(3) | |
curried2(4) // Prints: 1 2 3 4 | |
val curried3 = printFourThings("Red") | |
val curried4 = curried3("Green", "Blue") | |
curried4("Yellow") // Prints: Red Green Blue Yellow |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment