https://kotlinlang.org logo
#arrow-meta
Title
# arrow-meta
b

Ben Woodworth

12/06/2019, 11:42 PM
Hello! I'm interested in making a simple plugin, and I need a little help figuring out where to start.
Copy code
// Defined in a "common" sourceSet
interface Dependency {
    // member definitions
}

// Defined in other platform-specific sourceSets, with varying class/package names
@PlatformType
interface PlatformDependency : Dependency {
    // more platform-specific member definitions
}
In each platform-specific sourceSet of my codebase, anytime there's a
Dependency
instance, it's guaranteed to be a
PlatformInstance
. That can be denoted with
@PlatformType
, and I want to write a plugin and treats
Dependency
types (in this case) as `PlatformDependency`s everywhere within that sourceset. Right now I'm manually upcasting, but that's verbose/tedious. Is this possible/easy-ish to do? And where's a good place for me to start?
👋 1
❤️ 1
i

Imran/Malic

12/06/2019, 11:49 PM
sounds like your trying to write an type-alias ? If not please rephrase the goal of
@Platform
b

Ben Woodworth

12/06/2019, 11:58 PM
I updated the code example for clarity. Members are added by
PlatformDependency
. My use case is similar to kotlin multiplatform, except I can't use expect/actual, since all the sourceSets are compiled into a single jar, and the classpaths can't overlap each other.
r

raulraja

12/07/2019, 1:33 AM
@Ben Woodworth just finished KC but I can help this week with this when I get back home if nobody can't help before then. As I understand this plugin will just selectively generate members based on an annotation that tells which platform you are on. This should be doable with meta and I could help you find a way.
😀 1
👍 1
i

Imran/Malic

12/07/2019, 11:09 AM
This is just a draft, because I don’t know how your Platform looks like, wether it is a class or interface, etc. The next step is to get those members from the Platform and the quote above copy-pastes them. In addition you get those members synthetically in the ide for free.
💯 1
a

amanda.hinchman-dominguez

12/07/2019, 7:14 PM
Hey Ben! Welcome! Also coming back from KotlinConf but plan on looking tomorrow!
😁 1
b

Ben Woodworth

12/08/2019, 3:26 AM
Glad you guys are willing to help!! Arrow meta is a fascinating tool and I'm having fun playing around with it! I'll link to my actual codebase to help you get a better idea of what I'm doing Dependencies in the common sourceset (named
Fc...
). They're all interfaces, though I suppose there could be open classes as well: https://github.com/BenWoodworth/FastCraft/tree/master/src/common/kotlin/net/benwoodworth/fastcraft/platform Platform-specific dependencies (named
BukkitFc...
). Some classes/interfaces. These are the ones that'll be marked with
@PlatformType
: https://github.com/BenWoodworth/FastCraft/tree/master/src/bukkit/kotlin/net/benwoodworth/fastcraft/bukkit
❤️ 1
i

Imran/Malic

12/08/2019, 8:32 PM
I can take a look at it tomorrow,if you dont mind 🙂
a

amanda.hinchman-dominguez

12/08/2019, 9:55 PM
Whoops - Monday***
b

Ben Woodworth

12/09/2019, 1:30 AM
No rush guys. This is mostly a curiosity, and seemed like a good place to start learning :)
a

amanda.hinchman-dominguez

12/10/2019, 8:25 AM
@Ben Woodworth idk if Imran was able to help out but I have a layover later today and I can see if I can help out;
i

Imran/Malic

12/10/2019, 10:19 AM
Hey @Ben Woodworth 🙂 There are several ways to approach this, but from what I see in your project you can ditch code generation with quotes and use a more powerful abstraction we’re building. In particular, there is this pattern in your code base.
If we abstract this idea. You want to express an isomorphism between your common code base and your platform specific implementation. Instead of rolling out your own typeclass you can simplify this idea to the type system. For that we have
type-proofs
.
You can define an isomorphism between any Type regardless of its shape with
type-proof
, here is more: <https://kotlinlang.slack.com/archives/C1JMF6UDV/p1574244934048100?thread_ts=1574092607.040600&cid=C1JMF6UDV>.
From above your expressing an isomorphism between common
F
and all it’s platform specific abstractions
G
,
H
, etc..
both of these Functions can be lifted to the type system in a way, which gives you compile-time contracts for your Subtype relationship. That means the compiler is aware of both of these morphisms and can derive this SubType relationship a la Cart throughout your code base. Let’s cut it here and see how it looks in
Meta
This implementation is still naive, because you have to define every isomorphism per hand. A more elegant way is to use both
type-proofs
and rolling your own
typeclass
so those functions from below are auto-generated by the compiler.
An example for a more elegant way is here <https://kotlinlang.slack.com/archives/C0B9K7EP2/p1575842698103400?thread_ts=1575651112.087600&cid=C0B9K7EP2> As the library author you can decide how your typeclass in the example its
Semigroup
looks like. Btw, super awesome Minecraft plugin. @raulraja you should check it out here <https://www.spigotmc.org/resources/fastcraft.20544/>
@raulraja Please correct me if I got something wrong. 🙂
a

amanda.hinchman-dominguez

12/10/2019, 11:15 AM
@Imran/Malic @Ben Woodworth I think the main question I kind of have at the moment is the motivation behind using annotations to create a proof. I see the use of annotations for testing I believe - what do we typically create them in Arrow for? This is something I'm less familiar with
I also lean towards finding ways to not use them, personally - but that doesn't mean I'm knocking it 😄
It's just something I haven't had a chance to ask about yet!
i

Imran/Malic

12/10/2019, 11:20 AM
@Ben Woodworth I should have added that you get synthetic resolution for free in the ide and the compiler if you use this technique.
r

raulraja

12/10/2019, 11:59 AM
While this can be easily solved with type proofs and type tagging, type proofs are not ready yet to be used
they are still in development and it will frustrate you, quotes is a better approach and later you can revisit with typeproofs once they are in the snapshots
That is why in KC despite the Union example being powered by type proofs these were not mentioned
i

Imran/Malic

12/10/2019, 12:01 PM
Agree 🙂. It’s better because the API is still under development.
I just wanted to highlight what options are possible. But
quotes
can do the same.
a

amanda.hinchman-dominguez

12/10/2019, 12:03 PM
and much easier to use 🙂
b

Ben Woodworth

12/10/2019, 9:43 PM
There's a lot to take in here, but I think I get the gist of it, and it's got my cogs churning 🙂 @amanda.hinchman-dominguez
I think the main question I kind of have at the moment is the motivation behind using annotations to create a proof...
If you mean why I have
@PlatformType
, that's just the first idea that came to mind, so the classes/interfaces could be easily identified. But that's just because I've used them in the past for annotation processing and code generation. I'm definitely interested in seeing what other options there are!! @Imran/Malic Type proofs have crossed my mind (as well as using contracts somehow), but I didn't realize they could be defined concretely with
@Proof
annotations. I'm excited to see that be released, because it seems like a powerful tool I could make use of! As for
quotes
, I'm not sure I know what that is precisely. Is that related to the hello world plugin, where a function definition is substituted with Kotlin code within a string? And how would I make use of them here?
👌🏽 1
r

raulraja

12/10/2019, 10:13 PM
In this case you could use quotes to intercept the annotated element and codegen based on the current platform in the same declaration any members you wish
Similar to how it's done in the hello world
You can inspect anything you want from the tree to decide what to codegen in any arbitrary point of the tree or separate files
😁 1
a

amanda.hinchman-dominguez

12/11/2019, 3:58 PM
@Ben Woodworth I am giving a google hangout this Friday about the quote system from 12-2pm CST this Friday, but basically, we allow you to intercept underlying components of the tree accessed by the kotlin compiler with the quote-and-template system
❤️ 1
You can directly intercept AST elements and apply any transformation using the template system
for example:
Copy code
private fun ElementScope.toFlatMap(
  bind: KtProperty, 
  remaining: List<KtExpression>): Scope<KtExpression> {
  return """|${source}.flatMap { $argName $typeName -> 
            |  ${toFlatMap(remaining)}  
            |}""".expression
}
You can access properties directly in templating (used to replace declarations you intercept) because normally in code generation, you have to parse it out yourself!
👍 1
b

Ben Woodworth

12/11/2019, 10:29 PM
I should be free when you're doing the hangouts call, so I might pop in!
a

amanda.hinchman-dominguez

12/11/2019, 10:30 PM
sounds great!