Skip to content

Instantly share code, notes, and snippets.

View jducoeur's full-sized avatar

Justin du Coeur, AKA Mark Waks jducoeur

View GitHub Profile
@patrickjcurran
patrickjcurran / Algebras.md
Last active December 3, 2018 20:14
Vistors, F-Algebras, and Transducers

Vistors, F-Algebras, and Transducers

So Doug made an interesting PR, which uses the visitor pattern described in Haoyi's post.

As I was trying to understand the vistor pattern, I wanted to see how it compared to using F-algebras.

Haoyi describes the benefits of the vistor pattern to include:

  • Composability
  • Not creating intermediate datastructures
@odd
odd / LocalExecutor.scala
Last active May 25, 2019 15:27
LocalExecutor allows executing callback code locally inside an actor (where the actor state can be safely modified)
import akka.actor._
import scala.concurrent.duration.Duration
import scala.concurrent.{CanAwait, ExecutionContext, Future, TimeoutException}
import scala.util.{Failure, Success, Try}
object LocalExecutor {
private case class Execute(runnable: Try[Runnable])
private class LocalExecutionContext(target: ActorRef) extends ExecutionContext {
override def execute(r: Runnable) = target ! Execute(Try(r))
@sadache
sadache / 1-post.md
Created September 5, 2012 22:14
Applicatives are too restrictive, breaking Applicatives and introducing Functional Builders

This post aims to document a practical design implementation we came up with when designing some APIs in Scala. Of course the concept is not Scala specific and applies to other functional languages.

If you don't want to go into the full introduction, this post talks about how Applicatives are too restrictive and breaking them into two independent components can be interesting for Contravariant and Invariant Functors. Jump to implementation attached.

We are taking JSON serialization/deserialization as a motivating example.

JsValue is the name of the type that represents the JSON AST. What we need is to be able to read a JsValue and produce an A:

trait Reads[A]{
@milessabin
milessabin / gist:1705644
Created January 30, 2012 17:47
Access to companion object of Foo via implicit resolution
trait Companion[T] {
type C
def apply() : C
}
object Companion {
implicit def companion[T](implicit comp : Companion[T]) = comp()
}
object TestCompanion {
@ryan-williams
ryan-williams / monad-monoid.md
Last active March 14, 2020 19:51
Attempt to articulate an intuitive understanding about why "a monad is a monoid in the category of endofunctors"™️

a monad is just a monoid in the category of endofunctors

Monoid

A monoid has two components:

id (or empty)

"make an instance from nothing"

  • 0 (Unit => Int)
  • "" (Unit => String)
  • Nil (Unit => List[_])
@djspiewak
djspiewak / streams-tutorial.md
Created March 22, 2015 19:55
Introduction to scalaz-stream

Introduction to scalaz-stream

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

Why you prefer cats instead of zio? TF? It’s looks like zio ecosystem more widely and zio 2.0 has better performance What do you think?

Great question!

Performance-wise, it really depends on what you're doing. The problem with benchmarks (including the ones posted for ZIO and Cats Effect) is that they apply only to abstract situations, which are often nothing like what you see in real applications. A great write-up on this problem by Daniel Spiewak here, he wrote it better than I ever could: https://gist.github.com/djspiewak/f4cfc08e0827088f17032e0e9099d292

Also, this is not an app meant for production - I don't care that much about performance under load because there will be no load. And individual operations will often be bounded by I/O anyway, so the efficiency of the underlying runtime is likely not going to make a noticeable difference in use. Then again, both the client and server are JVM apps, so even the start-up penalty of the client will slow us down than picking even the least efficient e

Revisiting Tagless Final Interpreters

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

What follows are some of my (very) rough thoughts on what we can and should do with respect to CPS transformation in Scala at the language level. I'll try to start with some motivation behind my thinking, as well as some rambling observations on the nature of the problem space, but don't expect too much coherence here. :-)

The Problem

Async programming is hard.

Okay let's actually be more specific than that. High-performance I/O is hard. Signal multiplexing is a powerful technique for achieving high(er) performance I/O, particularly network I/O, but the tradeoff is that, in order to utilize it, the user-space programming model must allow for suspension and resumption of sequential continuations (often called "fibers" or "coroutines"). Achieving this type of programming model without significant tradeoffs in usability is what is exceptionally hard.

If that wasn't bad enough though, these problems are inextricably conflated with another set of problem spaces which are, themselves, very difficult. In