arrow-kt / arrow

Λrrow - Functional companion to Kotlin's Standard Library
http://arrow-kt.io
Other
6.13k stars 441 forks source link

Error when use Option.applicative().tupled #707

Closed KhoaSuperman closed 6 years ago

KhoaSuperman commented 6 years ago

Hi everybody, please help me to work out this issue. I tried using arrow in Android and Intellij project, Datatypes "Option" works fine but if I use Option.applicative().tupled then this error happen. I tested on example project https://github.com/dcampogiani/AndroidFunctionalValidation but didn't work.

Exception in thread "main" java.lang.ClassNotFoundException: arrow.core.Tuple3MonoidInstanceImplicits at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:264) at arrow.TypeclassResolutionKt.instanceFromImplicitObject(TypeclassResolution.kt:174) at arrow.TypeclassResolutionKt.instance(TypeclassResolution.kt:123) at khoaha.katana.kotlin_arrow.data_type.TestOptional$Companion.testApplicative(TestOptional.kt:99) at khoaha.katana.kotlin_arrow.data_type.TestOptional$Companion.test(TestOptional.kt:63) at demo.TestKt.main(Test.kt:6)

Process finished with exit code 1

raulraja commented 6 years ago

@KhoaSuperman Arrow does not yet declare Monoid instances for Tuple3. What's in TestOptional.kt ?

KhoaSuperman commented 6 years ago

@raulraja Thank for quick reply

Intellij Project: Here is my code:

val tupled = Option.applicative().tupled(Some(1), Some("Hello"), Some(20.0))
with(tupled.fold()){
        println(a)
        println(b)
        println(c)
 }

my build.gradle:

allprojects {
    repositories {
        jcenter()
    }
}

buildscript {
    ext.kotlin_version = '1.2.21'

    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

group 'khoahoang'
version '1.0-SNAPSHOT'

apply plugin: 'kotlin'
apply plugin: 'idea'
apply plugin: 'kotlin-kapt'

idea {
    module {
        sourceDirs += files(
                'build/generated/source/kapt/main',
                'build/generated/source/kaptKotlin/main',
                'build/tmp/kapt/main/kotlinGenerated')
        generatedSourceDirs += files(
                'build/generated/source/kapt/main',
                'build/generated/source/kaptKotlin/main',
                'build/tmp/kapt/main/kotlinGenerated')
    }
}

sourceSets {
    main.kotlin.srcDirs += 'src/main/myKotlin'
    main.java.srcDirs += 'src/main/myJava'
}

repositories {
    mavenCentral()
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    compile 'io.arrow-kt:arrow-core:0.6.1'
    compile 'io.arrow-kt:arrow-typeclasses:0.6.1'
    compile 'io.arrow-kt:arrow-data:0.6.1'
    compile 'io.arrow-kt:arrow-instances:0.6.1'
    compile 'io.arrow-kt:arrow-syntax:0.6.1'
    kapt    'io.arrow-kt:arrow-annotations-processor:0.6.1'
}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}

Android project: You can checkout the official example https://github.com/dcampogiani/AndroidFunctionalValidation then paste snippet below, the error will be throw in logcat

val tupled = Option.applicative().tupled(Some(1), Some("Hello"), Some(20.0))
raulraja commented 6 years ago

@KhoaSuperman I presume you are importing: arrow.typeclasses.Foldable#fold as an extension and that is why you are getting that error. We plan on removing those extensions that use the type class runtime lookup from arrow. I believe what you are trying to do here is:

import arrow.core.*
import arrow.typeclasses.*
import arrow.syntax.applicative.*

Option.applicative().map(Some(1), Some("Hello"), Some(20.0), { (one, hello, twenty) ->
   println(one)
   println(hello)
   println(twenty)
})

The applicative syntax (Applicative Builder) beside tupled contains also map which abstract over arity up to 10 args

KhoaSuperman commented 6 years ago

I tried your code and it works but actually here is what I'm doing:

import arrow.core.*
import arrow.syntax.applicative.tupled
import arrow.syntax.foldable.fold
import arrow.syntax.option.none
import arrow.syntax.option.some

Here is my source code if you need more details kotlin_arrow.zip

raulraja commented 6 years ago

@KhoaSuperman you can't do this at the moment because Arrow does not provide a Tuple3 instance for Monoid yet. You can add you own though to your project if you want until Arrow ships with one probably in a couple of releases around 0.8.0.

We have not created those instances as part of Arrow because they are just boilerplate and we don;t want to increase the size of the library adding instances for all the tuple arities. We are looking into a codegen mechanism to allow users that use those instances to generate whatever arities they need.

@instance(Tuple3::class)
interface Tuple3MonoidInstance<A, B, C> : Monoid<Tuple3<A, B, C>> {

    fun MA(): Monoid<A>

    fun MB(): Monoid<B>

    fun MC(): Monoid<C>

    override fun empty(): Tuple3<A, B, C> = Tuple3(MA().empty(), MB().empty(), MC.empty())

    override fun combine(a: Tuple3<A, B, C>, b: Tuple3<A, B, C>): Tuple3<A, B, C> {
        val (xa, xb, xc) = a
        val (ya, yb, yc) = b
        return Tuple3(MA().combine(xa, ya), MB().combine(xb, yb), MB().combine(xc, yc))
    }
}
KhoaSuperman commented 6 years ago

Nice. I will try and wait version 0.8.0. Thank for your help & support

raulraja commented 6 years ago

No problem! Cheers :beers: