Version: 2022.03.02
package example | |
trait Eq[A] { | |
def equal(x: A, y: A): Boolean | |
} | |
final case class Cofree[F[_], A](head: A, tail: F[Cofree[F, A]]) | |
object Cofree { | |
implicit def cofreeEq[F[_], A](implicit a: Eq[A], f: => Eq[F[Cofree[F, A]]]): Eq[Cofree[F, A]] = |
I was talking to a coworker recently about general techniques that almost always form the core of any effort to write very fast, down-to-the-metal hot path code on the JVM, and they pointed out that there really isn't a particularly good place to go for this information. It occurred to me that, really, I had more or less picked up all of it by word of mouth and experience, and there just aren't any good reference sources on the topic. So… here's my word of mouth.
This is by no means a comprehensive gist. It's also important to understand that the techniques that I outline in here are not 100% absolute either. Performance on the JVM is an incredibly complicated subject, and while there are rules that almost always hold true, the "almost" remains very salient. Also, for many or even most applications, there will be other techniques that I'm not mentioning which will have a greater impact. JMH, Java Flight Recorder, and a good profiler are your very best friend! Mea
tl;dr Generate a GPG key pair (exercising appropriate paranoia). Send it to key servers. Create a Keybase account with the public part of that key. Use your keypair to sign git tags and SBT artifacts.
GPG is probably one of the least understood day-to-day pieces of software in the modern developer's toolshed. It's certainly the least understood of the important pieces of software (literally no one cares that you can't remember grep's regex variant), and this is a testament to the mightily terrible user interface it exposes to its otherwise extremely simple functionality. It's almost like cryptographers think that part of the security comes from the fact that bad guys can't figure it out any more than the good guys can.
Anyway, GPG is important for open source in particular because of one specific feature of public/private key cryptography: signing. Any published software should be signed by the developer (or company) who published it. Ideally, consu
Tageless Final interpreters are an alternative to the traditional Algebraic Data Type (and generalized ADT) based implementation of the interpreter pattern. This document presents the Tageless Final approach with Scala, and shows how Dotty with it's recently added implicits functions makes the approach even more appealing. All examples are direct translations of their Haskell version presented in the Typed Tagless Final Interpreters: Lecture Notes (section 2).
The interpreter pattern has recently received a lot of attention in the Scala community. A lot of efforts have been invested in trying to address the biggest shortcomings of ADT/GADT based solutions: extensibility. One can first look at cats' Inject
typeclass for an implementation of [Data Type à la Carte](http://www.cs.ru.nl/~W.Swierstra/Publications/DataTypesA
bin/kafka-topics.sh --zookeeper localhost:2181 --list
bin/kafka-topics.sh --zookeeper localhost:2181 --describe --topic mytopic
bin/kafka-topics.sh --zookeeper localhost:2181 --alter --topic mytopic --config retention.ms=1000
... wait a minute ...
Miles Sabin recently opened a pull request fixing the infamous SI-2712. First off, this is remarkable and, if merged, will make everyone's life enormously easier. This is a bug that a lot of people hit often without even realizing it, and they just assume that either they did something wrong or the compiler is broken in some weird way. It is especially common for users of scalaz or cats.
But that's not what I wanted to write about. What I want to write about is the exact semantics of Miles's fix, because it does impose some very specific assumptions about the way that type constructors work, and understanding those assumptions is the key to getting the most of it his fix.
For starters, here is the sort of thing that SI-2712 affects:
def foo[F[_], A](fa: F[A]): String = fa.toString
All of the below properties or methods, when requested/called in JavaScript, will trigger the browser to synchronously calculate the style and layout*. This is also called reflow or layout thrashing, and is common performance bottleneck.
Generally, all APIs that synchronously provide layout metrics will trigger forced reflow / layout. Read on for additional cases and details.
elem.offsetLeft
,elem.offsetTop
,elem.offsetWidth
,elem.offsetHeight
,elem.offsetParent
Every application ever written can be viewed as some sort of transformation on data. Data can come from different sources, such as a network or a file or user input or the Large Hadron Collider. It can come from many sources all at once to be merged and aggregated in interesting ways, and it can be produced into many different output sinks, such as a network or files or graphical user interfaces. You might produce your output all at once, as a big data dump at the end of the world (right before your program shuts down), or you might produce it more incrementally. Every application fits into this model.
The scalaz-stream project is an attempt to make it easy to construct, test and scale programs that fit within this model (which is to say, everything). It does this by providing an abstraction around a "stream" of data, which is really just this notion of some number of data being sequentially pulled out of some unspecified data source. On top of this abstraction, sca