https://kotlinlang.org logo
Title
r

robstoll

05/02/2018, 6:07 PM
fun <T> foo(t: T){
    val i: (T) -> T = { it }
}
m

marcinmoskala

05/02/2018, 7:13 PM
inline fun <reified T> makeId() = { x: T -> x }
But it is not what I am looking for 😕 I wanted something like Haskell
id :: a -> a
id x = x
r

robstoll

05/02/2018, 7:21 PM
and what for? 🙂 with type erasure in place I doubt that it is possible to escape a scope where T is actually known (or you lose type safety)
m

marcinmoskala

05/02/2018, 7:22 PM
inline fun <reified T> id() = { x: T -> x }

val double = { i: Int -> i * 2 }

infix fun <A, I, R> ((I)->R).after(f: (A)->I) = { a: A -> this(f(a)) }

fun main(args: Array<String>) {
    val f = double after id() after id() after double after double after id()
    print(f(1)) // 8
}
😄
Close to perfect 😄
Perfect would be to do:
val f = double after id after id after double after double after id
r

robstoll

05/02/2018, 7:23 PM
wait a minute 😄
m

marcinmoskala

05/02/2018, 7:23 PM
More Heaskell-like version:
inline fun <reified T> id() = { x: T -> x }
val double = { i: Int -> i * 2 }
operator fun <A, I, R> ((I)->R).times(f: (A)->I) = { a: A -> this(f(a)) }

fun main(args: Array<String>) {
    val f = double * id() * id() * double * double * id()
    print(f(1)) // 8
}
r

robstoll

05/02/2018, 7:27 PM
I think your problem here is, that Kotlin does not support currying as Haskell does
m

marcinmoskala

05/02/2018, 7:35 PM
Currying is not a problem. Lack of generic function type is. From language design point of view it might be possible:
val double = { i: Int -> i * 2 }
operator fun <A, I, R> ((I)->R).times(f: (A)->I) = { a: A -> this(f(a)) }
fun <T> id(x: T) = x

fun main(args: Array<String>) {
    val f = double * ::id * ::id * double * double * ::id
    print(f(1)) // 8
}
Or this:
val double = { i: Int -> i * 2 }
operator fun <A, I, R> ((I)->R).times(f: (A)->I) = { a: A -> this(f(a)) }
val id = fun <T> (x: T) = x

fun main(args: Array<String>) {
    val f = double * id * id * double * double * id
    print(f(1)) // 8
}
But it is not. I think the reason is that it would be extremely hard to implement in Java which have really primitive support for generic
r

robstoll

05/02/2018, 8:08 PM
how does the definition look like in Haskell? Looks like function composition with partial application (or in other words currying)
nah... you do not even do a partial application. you only do composition. I guess it's a bug in the infix notation
If I am not mistaken, this does the same:
fun <T> id(x: T) = x
fun <T, R, S> and(f: (T) -> R, g: (R) -> S): (T)-> S = {t -> g(f(t)) }
fun main(args: Array<String>) {
    val f = and(and(and(double, ::id), ::id), double)
    println(f(1))
}
oh... you made a mistake in your times function (unless you do not want function composition), the following works:
val double = { i: Int -> i * 2 }
fun <T> id(x: T) = x
infix fun <T, R, S> ((T) -> R).and(g: (R) -> S): (T)-> S = {t -> g(this(t)) }
fun main(args: Array<String>) {
    val f = double and double and ::id and ::id and double
    println(f(1))
}
nah... it's not a mistake, more a limitation in type inference
in my version kotlin can infer the type because it works from left to right were we already know, that we have Int -> Int on the left. In your version it wants to apply T -> T first and does not know what type it should use 😄
m

marcinmoskala

05/02/2018, 8:37 PM
You are right: If you rethink it, it is a problem with Kotlin type inference. This works:
val double = { i: Int -> i * 2 }
fun <A, I, R> ((I)->R).after(f: (A)->I) = { a: A -> this(f(a)) }
fun <T> id(x: T) = x

fun main(args: Array<String>) {
    val intId: (Int)->Int = ::id
    val f = double.after(intId)
    print(f(1)) // 2
}
r

robstoll

05/02/2018, 8:37 PM
it's not the
::id
which fails but the
times
operator
m

marcinmoskala

05/02/2018, 8:38 PM
Or even this:
val double = { i: Int -> i * 2 }
fun <A, I, R> ((I)->R).after(f: (A)->I) = { a: A -> this(f(a)) }
fun <T> id(x: T) = x

fun main(args: Array<String>) {
    val f = double.after<Int, Int, Int>(::id)
    print(f(1)) // 2
}
r

robstoll

05/02/2018, 8:39 PM
I am not aware of the internal of their type inference algorithm but they could improve on this one. Questionable how much it would cost
m

marcinmoskala

05/02/2018, 8:39 PM
Even this works:
val double = { i: Int -> i * 2 }
infix fun <A, I, R> ((A) -> I).then(f: (I) -> R) = { a: A -> f(this(a)) }
fun <T> id(x: T) = x

fun main(args: Array<String>) {
    val f = double then ::id
    print(f(1)) // 2
}
r

robstoll

05/02/2018, 8:39 PM
that's the same as my and above yes, that's again left to right which Kotlin can grasp
I'll open a issue and see what they say
m

marcinmoskala

05/02/2018, 8:41 PM
I've started writing
r

robstoll

05/02/2018, 8:42 PM
continue writing... I wanted to write I would not I will
m

marcinmoskala

05/02/2018, 8:47 PM
I must say it is funny problem 🙂 I am not at vacations but it was nice to check it out.
r

robstoll

05/02/2018, 9:18 PM
was nice looking into it 🙂
m

marcinmoskala

05/03/2018, 6:49 PM