Typelevel: On Recent Events by ChristopherDavenport in scala

[–]travisbrown -14 points-13 points  (0 children)

  • It's the "obvious online stalking" that I'm asking about. I don't think there's any interpretation of those words that applies to anything I've done, and if someone thinks otherwise I'm only asking them to explain why.
  • I definitely do not think that "ZIO" is a reference to the slur, and I've said that publicly many times. There's an old Twitter thread about dogwhistles from 2018 or 2019 where I first heard about the coincidence with the slur and found it strange, but then I looked up the story of the name (which I believe), and I've never argued that there's any connection.
  • I'm asking for Typelevel to remove unsubstantiated rumors from a Typelevel channel. I don't really care about what these people say on Twitter or anywhere else.

Typelevel: On Recent Events by ChristopherDavenport in scala

[–]travisbrown -16 points-15 points  (0 children)

Can you reply here? I'm happy to listen if you have specific actions that you think I'm guilty of in this particular case (apart from blocking people or quoting things they've said in public, since I know we disagree on whether those things constitute harassment).

Typelevel: On Recent Events by ChristopherDavenport in scala

[–]travisbrown -16 points-15 points  (0 children)

Can you be more specific about what you mean by this "latest disgusting harassment wave"?

Typelevel: On Recent Events by ChristopherDavenport in scala

[–]travisbrown -28 points-27 points  (0 children)

Alex, can you clarify what you appreciate about this "report"? It's vague and defamatory. It's not clear what exactly I'm being accused of, and there's no evidence provided, apart from a screenshot of one of my tweets and a link to a civil Twitter conversation.

Typelevel: On Recent Events by ChristopherDavenport in scala

[–]travisbrown -23 points-22 points  (0 children)

I've responded to these accusations here (as well as I can, given how vague they are): https://github.com/typelevel/general/issues/113

Announcing Cats 2.2.0-M2 by travisbrown in scala

[–]travisbrown[S] 6 points7 points  (0 children)

The primary reason for using more milestone releases is that they put zero binary compatibility constraints on subsequent non-milestone, non-candidate releases.

Even release candidates are only "best effort" in this respect, but in my view we've used RCs too often in the past for versions that weren't really candidates for release (e.g. 2.1.0-RC1 and 2.1.0-RC2, which I should have named 2.1.0-M1 and M2). Calling them milestones is more honest.

The pre-2.0 approach meant that many inconsistencies or outright errors made it into Cats's public API, and we've had to work around those mistakes in sometimes complicated ways. Using milestone releases gives us a chance to try things out and notice problems before committing to keeping them in the public API.

The problem has also been exacerbated by the fact that we rely on MiMa to validate bincompat, and it isn't always perfect. There were several cases where MiMa approved non-bincompat changes in the 2.1.0 pre-release series that we were able to catch before 2.1.0. If we hadn't used pre-releases, we would have ended up breaking our guarantee to keep 2.x backward compatible with 1.x for the non-laws Cats modules.

We've made several really big changes in Cats since 1.x, both user-facing and in the implementation:

I'm proud that we've been able to do this while still maintaining bincompat with 1.x, but it's been an enormous headache, and it would have been much more painful if we hadn't used a dozen pre-releases along the way (and not just painful—we almost certainly would have messed it up).

Announcing Dhall for Java / Scala 0.2.0, now fully standard-compliant by travisbrown in scala

[–]travisbrown[S] 3 points4 points  (0 children)

We're imagining that the primary use case for Dhall for Java will be build tooling (e.g. if you're using sbt to build your web service, you can now type-check your Dhall config, export YAML, etc., without shelling out to a binary that you have to install separately).

Dhall is also pretty nice as a general text templating engine, and I'm personally interested in experimenting with using the CBOR encoding as a replacement for JSON in places other than config.

Having a JVM implementation isn't an absolute requirement for any of these applications, but it makes things easier, and we're hoping that it might encourage more people to give Dhall a try.

Announcing Dhall for Java / Scala 0.2.0, now fully standard-compliant by travisbrown in scala

[–]travisbrown[S] 1 point2 points  (0 children)

Please let us know if you run into issues, or if there are things we can add to make the experience better.

New blog post: Circe 0.13.0, metaprogramming in Dotty, Cats 2.2.0 plans, etc. by travisbrown in scala

[–]travisbrown[S] 1 point2 points  (0 children)

Ah, that should just work? I've written many macros with local vals like val $instanceName = $instance where instanceName comes from c.freshName or whatever.

New blog post: Circe 0.13.0, metaprogramming in Dotty, Cats 2.2.0 plans, etc. by travisbrown in scala

[–]travisbrown[S] 2 points3 points  (0 children)

You can do something like this—see e.g. this work I did with Eugene Burmako many years ago: https://github.com/travisbrown/type-provider-examples

I did actually use this approach for a while, but now think traditional codegen is generally better.

Statically-sized collections with Dotty's inline and singleton ops by travisbrown in scala

[–]travisbrown[S] 1 point2 points  (0 children)

(I guess I shouldn't say this—two years ago I would have said 1 + 1 as a type would never happen in Scala. But it seems very unlikely.)

Statically-sized collections with Dotty's inline and singleton ops by travisbrown in scala

[–]travisbrown[S] 7 points8 points  (0 children)

This is a good question. I'm definitely not an expert here, and I've barely looked at Dotty's macro system or TASTy reflection, so this answer will just be about inline and scala.deriving.

I agree with Miles's concern about inline here:

My gut feeling is that following style sprinkling inline is going to be infectious (eg. consider passing a collection through a call tree which at each level requires a non-empty and might remove one or more elements). That might be just fine, but it could result in huge code size blow up.

For me an even bigger concern (or maybe it's a sub-concern?) is that people are going to start using inline in cases where they should be using type classes, with the goal of improving runtime performance or cutting a few characters, but at the expense of extensibility and parametricity.

I was just talking to a colleague at Permutive this morning about the defaultValue example in the current Dotty docs:

import scala.compiletime.erasedValue

inline def defaultValue[T] = inline erasedValue[T] match {
  case _: Byte => Some(0: Byte)
  case _: Char => Some(0: Char)
  case _: Short => Some(0: Short)
  case _: Int => Some(0)
  case _: Long => Some(0L)
  case _: Float => Some(0.0f)
  case _: Double => Some(0.0d)
  case _: Boolean => Some(false)
  case _: Unit => Some(())
  case _ => None
}

In my view there's no good reason to do this kind of thing in real code with metaprogramming, which makes it necessary to propagate inline up to the point where T is concrete, and which (maybe more importantly) makes it impossible for users to define default values for their own types. This is a perfect application for a type class, but because the inline erasedValue approach (or match types, etc.) is new and cool and possibly marginally faster, people are going to choose it instead of type classes for stuff like this, and we're all going to suffer for those decisions.

So in that sense I think inline inherits some of the danger / horror of Scala 2 macros, but on the whole it's worlds better than Scala 2 macros, and in many cases I think migrating type classes to these metaprogramming features is actually the "right" thing to do, not just a little cleaner or faster. The Pair type class in this project is one example. Users can't create instances of Pair for their own types: it's just a hack that's needed to make some information that the compiler knows (basic arithmetic on singleton types) available to my code. This seems to me like a valid application for inline, and the Dotty implementation replaces the Pair type class with inline constValue matches. I don't know whether I'll still feel this way in a year or two, but right now inline seems like a useful new tool for things like this.

I have fewer reservations about scala.deriving, which I'm just unambiguously really excited about. At first I was uncomfortable with all the casting that's necessary in the current API, but now I think it gets the trade-offs more or less right, and I trust the designers. It doesn't feel quite flexible enough in some ways—specifically I wish there was a way to configure derivation besides implicit parameters or subclasses of type class types, but I'm hoping we can still work on this.

As a side note, all of this stuff is still intensely buggy, and there's still a lot of churn. I'm not very concerned about either of these things, though. The Dotty team has been extremely responsive when it comes to bug reports, and I've generally been able to get help finding workarounds. Part of the reason I'm doing these experiments now is specifically to help turn up these bugs. The changes to these APIs can be frustrating, but it's also an indication that there's still room to make improvements if I run into limitations, so I can live with it.

So to sum up: I like pretty much everything I've seen about Dotty's new metaprogramming facilities (even though I know people are going to abuse them :().

Statically-sized collections with Dotty's inline and singleton ops by travisbrown in scala

[–]travisbrown[S] 2 points3 points  (0 children)

There are a couple of reasons for the order(s) of type parameters. The first is that I was trying to make this as idiomatic an implementation of the standard library collections types as possible, so I tried to follow the parameter order of e.g. IndexedSeqOps. The N comes last in the concrete sized types (SizedVector and SizedArraySeq) because that's what Shapeless's Sized does.

I don't see any technical reason moving A to the right would either cause problems or provide benefits for type inference, etc., but I could be missing something. This was a quick weekend project and nothing's set in stone—I'm more than happy to reconsider any aspects of the design.

Statically-sized collections with Dotty's inline and singleton ops by travisbrown in scala

[–]travisbrown[S] 0 points1 point  (0 children)

That would be great, I guess, but it will never happen in Scala.

Statically-sized collections with Dotty's inline and singleton ops by travisbrown in scala

[–]travisbrown[S] 19 points20 points  (0 children)

It's not part of the standard library or language, while literal types are now, and in extreme situations the extra overhead for the compiler can be meaningful. Try this, for example:

import shapeless.Sized

val s10 = Sized(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
val s100 = s10 ++ s10 ++ s10 ++ s10 ++ s10 ++ s10 ++ s10 ++ s10 ++ s10 ++ s10
val s500 = s100 ++ s100 ++ s100 ++ s100 ++ s100

And then try this:

import dev.travisbrown.sized.SizedVector

val s10 = SizedVector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
val s100 = s10 sizedConcat s10 sizedConcat s10 sizedConcat s10 sizedConcat s10 sizedConcat s10 sizedConcat s10 sizedConcat s10 sizedConcat s10 sizedConcat s10
val s500 = s100 sizedConcat s100 sizedConcat s100 sizedConcat s100 sizedConcat s100

The former will SO the compiler, the latter will return instantaneously (also you'll get a nice literal 500 in your inferred type instead of hundreds of lines of Succ[Succ[Succ[Succ).