Hi, all. As many of you know I am in the process o...
# arrow
m
Hi, all. As many of you know I am in the process of translating the Scala Red Book into Kotlin (aka, the Orange Book). I am progressing well and am currently at work on Chapter 9 about writing a purely function parsing library. I have run across the first constraint in the language where I would need input from my Arrow friends! Here is the problem: I need to declare an interface that has nested type parameters (which Kotlin does not support). This is how it looks in Scala:
Copy code
trait Parsers[ParseError, Parser[+_]] {
  def run[A](p: Parser[A])(input: String): Either[ParseError, A]
  def char(c: Char): Parser[Char]
}
The problem of course comes when declaring the type constructor
Parser[+_]
, and when you subsequently try to use a
Parser
without the type constructor present, we get an error on the
char
parser declaration to the effect of "_type arguments not allowed for type parameters"_. I was hoping that I could use
Kind
to solve this problem but not sure how to go about it. Any help would be greatly appreciated!
🙌 5
🔝 3
arrow 5
a
Hi there Marco! Thanks for taking the effort on doing so (I think it’s a great initiative BTW) and for choosing Arrow 🙂
👍 1
i’m not totally sure about what are those explicit type parameters doing in the trait, but here’s a version in kotlin that might work as well
Copy code
object ParseError

class ForParser private constructor() {
  companion object
}

@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
inline fun <A> ParserOf<A>.fix(): Parser<A> =
  this as Parser<A>

typealias ParserOf<A> = arrow.Kind<ForParser, A>

class Parser<A> : ParserOf<A> {

}

interface Parsers {
  fun <A> run(p: Parser<A>, input: String): Either<ParseError, A>
  fun char(c: Char): Parser<Char>
}
all the ForParser, ParserOf and the fix is some necessary boilerplate for now that will be removed at a later point with Meta
m
That is exactly what I was looking for, thanks @aballano!
🙌 1
Is there any idea about when this will all be rolled into Meta?
It would make explaining this a lot easier to the readers of the book 😆
a
we’re currently doing some experiment trying to migrate some modules to it, but it’ll take couple of weeks still
well it might be a timing thing, depending when do you plan to release it I guess 😄
m
I think I will put the boilerplate in the book for now without too much explanation, then update the code samples when meta supports this.
a
yes, i think that’s a good approach 👍
m
That's the nice thing about this MEAP process, you can evolve the content of the book as it goes along.
👌 2
Thanks for you help!
a
you’re welcome! please let us know if you have any other question, we’d love to help 😊
r
If you need to refer to something there are two sections here that cover the kind emulation https://arrow-kt.io/docs/patterns/glossary/#type-constructors
👌 2
j
Sticky fingers also sent this to the channel... Yay
Btw, a while ago I wrote a parser combinator library that is (mostly) equal in features to haskell's megaparsec: https://github.com/1Jajen1/Kparsec Because of the delayed university start I actually have time to document this now :) because of megaparsecs efforts to make errors superb it is a lot more complicated, but if anyone is interested I could walk through the basics ^^ this is for now best to describe the features: https://markkarpov.com/tutorial/megaparsec.html almost all of it while slightly different is working in kotlin
❤️ 3
Also @kartoffelsup experimented with a kotlin parser combinator setup a while ago, he might have a link to an easier less powerful approach
m
@aballano stupid question, but is there a way to tie this back into the interface declaration? It doesn't feel like we've consolidated
Parsers
with
Parser
yet in your example code so as to give us the equivalent of
trait Parsers[ParseError, Parser[+_]]
in the Scala variant.
p
Copy code
interface Parser<A> : ParserOf<A>

interface Parsers<ParseError> {
  fun <A> run(p: ParserOf<out A>, input: String): Either<ParseError, A>
  fun char(c: Char): Parser<out Char>
}
that?
I’m not sure if it’s valid syntax
it is, huh
m
Awesome, thanks @pakoito! Works like a charm.
p
parser isn’t covariant there tho
fun char(c: Char): Parser<out Char>
in this position it’s invariant
k
I basically just tried to implement what is done in this video in arrow:

https://www.youtube.com/watch?v=N9RUqGYuGfw

https://github.com/kartoffelsup/haskell-inspired-arrow-json-parser
😍 1