marioariasc / funktionale Goto Github PK
View Code? Open in Web Editor NEWFunctional constructs for Kotlin
Functional constructs for Kotlin
sealed class Either<out L : Any?, out R : Any?>(protected open val l: L?, protected open val r: R?) {
class Left<out L : Any>(override val l: L) : Either<L, Nothing>(l, null) {
override fun <T1 : Any, T2 : Any> map(ifLeft: ((L) -> T1)?, ifRight: ((Nothing) -> T2)?) = Left(ifLeft!!.invoke(l))
override fun swap() = Right(l)
override fun <T> case(left: ((L) -> T)?, right: ((Nothing) -> T)?) = left!!.invoke(l)
override fun <C> case(left: C, right: C) = left
override fun toString() = "Left: $l"
override fun equals(other: Any?) = this === other || (other is Left<*> && l == other.l)
override fun hashCode() = l.hashCode()
}
class Right<out R : Any>(override val r: R) : Either<Nothing, R>(null, r) {
override fun <T1 : Any, T2 : Any> map(ifLeft: ((Nothing) -> T1)?, ifRight: ((R) -> T2)?) = Right(ifRight!!.invoke(r))
override fun swap() = Left(r)
override fun <T> case(left: ((Nothing) -> T)?, right: ((R) -> T)?) = right!!.invoke(r)
override fun <C> case(left: C, right: C) = right
override fun toString() = "Right: $r"
override fun equals(other: Any?) = this === other || (other is Right<*> && r == other.r)
override fun hashCode() = r.hashCode()
}
fun isLeft() = l !== null
fun isRight() = r !== null
fun left() = l!!
fun right() = r!!
abstract fun <C> case(left: C, right: C): C
abstract fun <T> case(left: ((L) -> T)?, right: ((R) -> T)?): T
abstract fun <T1 : Any, T2 : Any> map(ifLeft: ((L) -> T1)?, ifRight: ((R) -> T2)?): Either<T1, T2>
abstract fun swap(): Either<R, L>
}
That's much easier to read and use
I was able to build v1.2 and publish to my local nexus repo, but it might be useful for you to publish to mavenCentral or another publicly available repo and update the mavenCentral.com details for the module.
scala is
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
Hi Mario,
thank you very much for funKTionale!
I have a question regarding memoization of member functions. I'm used to Java and Groovy and a Kotlin Newbie.
Maybe you have some time and can give some insights on this...
I'd like to memoize the sum
member function of this immutable data class (just a silly example)
package tryout
data class MyDataClass(val a: Int = 1,
val b: Int = 2) {
fun sum(): Int {
println("Calculating...")
return a + b
}
}
fun main(args: Array<String>) {
val myData = MyDataClass()
println(myData.sum())
println(myData.sum())
println(myData.sum())
}
In groovy I can do this using an annotation
package tryout
import groovy.transform.CompileStatic
import groovy.transform.Immutable
import groovy.transform.Memoized
@CompileStatic
@Immutable
class MyGroovyDataClass {
int a, b
@Memoized
int sum() {
println("Calculating...")
a + b
}
static void main(String[] args) {
def myData = new MyGroovyDataClass(1, 2)
println(myData.sum())
println(myData.sum())
println(myData.sum())
}
}
If I want to do this using funkTionale, then there is at the moment "only" this solution, right?
package tryout
import org.funktionale.memoization.memoize
data class MyMemoizedDataClassV1(val a: Int = 1,
val b: Int = 2) {
private val memoizedSum: (Int, Int) -> Int = { i: Int, j: Int ->
println("Calculating...")
i + j
}.memoize()
fun sum(): Int {
return memoizedSum(a, b)
}
}
fun main(args: Array<String>) {
val myData = MyMemoizedDataClassV1()
println(myData.sum())
println(myData.sum())
println(myData.sum())
val myData2 = myData.copy(b = 99)
println(myData2.sum())
println(myData2.sum())
println(myData2.sum())
val myData3 = myData2.copy(a = 101)
println(myData3.sum())
println(myData3.sum())
println(myData3.sum())
}
Or is there a "more direct" solution?
Thanks for your time & best regards,
Peti
Hi,
Have you thought about adding constructs similar to Haskell's "do notation" or Scala's "for comprehension" to avoid nesting (something like Komprehensions)? Does it make sense or do you consider this to be out of scope?
Regards,
/Johan
Absence of license raises the question whether I can use this library in my code.
It sounds from https://www.47deg.com/blog/announcing-arrow-for-kotlin/ like this project has been replaced by Arrow—if that's true, could you add a note to that effect to the top of the readme?
repositories {
mavenCentral()
jcenter()
maven { url "https://jitpack.io" }
}
dependencies {
compile 'org.funktionale:funktionale:1.2'
}
In your talk you said you have a script to generate functions like this:
infix inline fun <P1, R> P1.pipe(t: (P1) -> R): R = t(this)
infix inline fun <P1, P2, R> P1.pipe2(crossinline t: (P1, P2) -> R): (P2) -> R = { p2 -> t(this, p2) }
infix inline fun <P1, P2, P3, R> P1.pipe3(crossinline t: (P1, P2, P3) -> R): (P2, P3) -> R = { p2, p3 -> t(this, p2, p3) }
Would you mind sharing it?
I want to automate the generation of functions like that.
The name of the second argument "f" like a not very good solution. I like to use named argument for fold calling and any more functions.
Of course, I can write:
fold(isEmpty = {...}){value -> ...}
But I want to be able to write like this
fold(isEmpty = {...}, some = {value -> ...})
Functions like eitherTry
and Try
would also be useful when catching exceptions thrown by suspending functions. The current implementations don't support this. For example, I cannot to this:
fun main(args: Array<String>) = runBlocking {
val a = async<String>(CommonPool) {
throw Throwable()
}
val result = eitherTry {
a.await()
}
println(result)
}
This fails to compile on a.await
because we are not in a suspending block.
I see two potential solutions:
eitherTry
becomes suspend fun <T> eitherTry(body: suspend () -> T): Either<Throwable, T>
inline
.Hi!
I just wanted to clarify whether it was a design decision to make Either
unbiased. As far as I remember, the only unbiased version of Either
in the Scala world is ancient scala.util.Either
and it's criticized by everyone left and right for exactly its unbiased nature.
Pretty much all alternatives including scala.util.Try
, scalaz.\/
or cats.data.Xor
are right-biased. In your wiki you are also pointing out that
Traditionally the Left represent an error and Right a correct return
So, why not make it right-biased by design and provide map
and flatMap
? It would make it even more useful.
Thank you for a great library!
funKTionale has no license file.
What license is it released under?
Thanks!
I used memoization in Scala before and had issues when two different threads tried to call the memoized function. (The issue was that the memo used a non-thread safe "regular" HashMap and that caused it misbehave. However, I also tried creating a custom memo implementation using ConcurrentHashMap and I seem to recall that had performance issues).
The question---is the underlying memo implementation thread safe?
Hi there.
Is there a method which returns Option.None
like Scala.
I tried to find the method but I couldn't.
Hi,
when using this library on Android 4.2 and older, I get an INSTALL_FAILED_DEXOPT. It might have something to do with this problem: http://stackoverflow.com/questions/21434837/installing-kotlin-android-project-fails-with-install-failed-dexopt
After recompiling funKTionale with latest Kotlin (Beta 2), everything works fine. Could you please upload a recompiled version to the official maven repo? Many thanks.
Can I transform function like
fun myProc(a:Int, b: String, c: Float)
to
fun myProc(c:Float)
in one step?
Right now I use code
myProc.partially1(1).partially1("")
, but maybe there are best solution?
I figured that in my compilation problem with gradle 3.0 described here [1] the reason is in fact funktionale. I cannot pinpoint it any further but I suppose it's a good idea to report it here. It used to compile just fine before I updated my build environment.
operator fun <P1, P2, R> Function2<P1, P2, R>.invoke(p1: P1) =
{ p2: P2 -> this(p1, p2) }
operator fun <P1, P2, P3, R> Function3<P1, P2, P3, R>.invoke(p1: P1) =
{ p2: P2, p3: P3 -> this(p1, p2, p3) }
operator fun <P1, P2, P3, P4, R> Function4<P1, P2, P3, P4, R>.invoke(p1: P1) =
{ p2: P2, p3: P3, p4: P4 -> this(p1, p2, p3, p4) }
val foo: (Int, Int, Int) -> Int = { a, b, c -> a + b + c }
fun bar(a: Int, b: Int, c: Int) = a + b + c
fun main(args: Array<String>) {
foo(1, 2, 3)
foo(1)(2)(3)
bar(1, 2, 3)
(::bar)(1)(2)(3)
}
I've been doing some experiments with Either myself and what I came up with has IMO a nice way of mapping either choice in a concise fashion, you might want to take a look at it and see if this is something for funktionale-either. It appears to be what Either is doing in fold
but expanded by infix operations.
Relevant code starts here:
https://gist.github.com/lukashaertel/02b8dd4a5ad8c691bc783eb7b88fba9b#file-choice-kt-L37
And here's an example of how it's applied:
// A method handling that choice type
val f = { u: Choice<Number, String> ->
// Map either side accordingly
val d = u onLeft {
it.toDouble() / 2
} onRight {
it.length.toDouble()
}
println(d)
}
I'd like to use this library in an application of mine. Would you be willing to add an open source license like Apache or MIT to the project? I could create a pull request to do it if you'd like.
Functions like Try<T>.flatMap
and Try<T>.fold
swallow RuntimeExceptions, making it harder to find bugs.
For example, I tried to use a TODO()
, but my application did not terminate:
fun main(args: Array<String>) {
val result = Success("Test").flatMap<Unit> { TODO() }
println(result)
}
Instead, the console prints
Failure(kotlin.NotImplementedError: An operation is not implemented.)
In Rust, the stdlib provides an Either like enum called Result. Functions that return Result can also carry values from other Result returning functions up the call stack. So if you're performing disk IO, where you'll be getting Result types as returns based off of whether there was an error opening a file, writing to disk etc. All this can be represented by a macro, or an operator.
fn i_return_a_result() -> Result<String, std::io::Error> {
let i_returned_a_result: File = file_operation_that_returns_result()?;
try!(write_to_file(i_returned_a_result));
Ok("We did it!".to_string())
}
To those not familiar with Rust, let me explain.
The function declaration is similar to one you would find in Haskell or using FunKTionale using Either, with the difference being that the left side is the result, and the right side is the error, exception, or what have you. In the function body, there were 2 instances where I would have needed to deal with checking that there was a proper value in the result. When I get the file, and when I write (I didn't bind a variable in that case, because it's often used that functions return a Result with an empty left side, just indicating success).
In both cases, were there an error at any point¸ my function would have stopped executing, and the Error from their result would propogate up as the return value of my function, allowing it to be dealt with at the top.
Would this be at all possible in funcKTionale? Taking a Either returning function and collapsing it down to either give you the value of Right, or return from your function with the value of left?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.