hey, quick question: I have just been pointed towa...
# arrow
f
hey, quick question: I have just been pointed towards the (haskell) concepts of "SYB/uniplate/Control.Lens.Plated" to use instead of the typical visitor pattern for rewriting abstract syntax trees. Does Arrow have anything in that direction already? Arrow has something called
Lens
as part of the
Optics
component, but I don't know if this is the same idea, and because I am not familiar with those concepts already, I'd rather focus on learning and understanding the thing I actually need for my project, not something else that happens to have the same name 😅
s
Hey Florian, I think the Optic you're looking for is called
Plated
, and not actually
Lens
.
f
So there is a
Plated
optic ? I only checked the docs at https://arrow-kt.io/docs/optics/ so far
s
The
Lens
type you mentioned doesn't cover the functionality you're looking for, but the
Plated
type can easily be build in Arrow/Kotlin.
I prototyped the Plated Optic once, but never polished it enough to put it into Arrow
f
ah, that would have been my subsequent question: How hard would it be to build.
Do you have the prototyped code somewhere? Would be interested
s
I was sure it'd be lost but I found it 😄 It's quite easy to build. That branch also has some tests, and instances for
Plated
you can take a look at in the last couple commits. https://github.com/arrow-kt/arrow-optics/blob/simon-plated/arrow-optics/src/main/kotlin/arrow/optics/typeclasses/Plated.kt
f
Making no guarantees, but I do have the habit of spending way too much time polishing the underlying abstraction instead of fixing my actual problem 🙃
s
It should be pretty easy to clean up
Last 3 commits has all the code you need, including tests.
f
What aspects of this do you consider "unclean"? I haven't dealt with this kind of functional code yet, but I'm curious and this seems like an interesting example to learn
s
It's not unclean perse, it's just a bit outdated by now. For example
SequenceK
no longer exists, and you should just use
Sequence
from Kotlin Std. I'm not sure Plated is as useful in Kotlin as it's in Haskell though.
f
yeah, not sure about how useful this is either. My visitor pattern based class currently already allows pretty concise code, not sure how much better this gets with fancy functional abstractions
s
My guess would be that if you have a decent API / DSL for the visitor pattern then that'll probably result in nicer and more idiomatic Kotlin code.
If you have any interesting findings, I'd love to hear them though 🙂
f
Mmh, currently it's basically "subclass the ASTVisitorBase and override the method corresponding to the expressions you want to rewrite"
so in theory something like "rewrite x + x to x * 2" would be just
Copy code
class MulTwoRule: CopyVisitor {
    override fun visitAddition(expr: Addition): Expression {
        if (expr.rhs == expr.lhs) return Multiplication(expr.rhs, 2)
        else {
            return super.visitAddition(expr) // basically a copy
        }
    }
}
eh,
Multiplication(visit(expr.rhs), 2)
otherwise, that subexpression isn't actually handled
Not sure how well this pattern works when composing many rules though
s
With plated I think that would be:
Copy code
with(Plated.expression()) {
  expression..transform { case ->
    when(case) {
      is Addition -> if (expr.rhs == expr.lhs) Multiplication(expr.rhs, 2) else case
      else -> case
    }
  }
}
Where you would just compose your different rules inside of the
(Expression) -> Expression
block.
But I don't have a lot of experience with it
f
In my use case I want to aggregate those rewrite rules from different sources, e.g. that it is easily possible for a user to add a new rule. So composing them in one central block isn't really an option anyway
but yeah, the way with plated doesn't feel that much more concise
s
You can create your external API however you want, it somehow needs to be passed down to this eventually but like I mentioned before I am personally skeptical this would result in a nicer or more performant solution. Kotlin has really amazing support for making really nice DSLs, and I would probably advise looking into that instead.
f
thank you very much for the feedback! Looking deeper into Kotlin DSLs sounds good, will keep that in mind
👍 1