Skip to content

Instantly share code, notes, and snippets.

import cats._
// A pure functional, contravariant monoidal string builder
sealed trait SB[A] {
final def render(a: A): String = {
val sb = new StringBuilder
renderInternal(sb, a)
sb.toString
}
@SystemFw
SystemFw / Ex.scala
Created October 26, 2018 20:39
Get instances of a typeclass `TC[_]` for all cases of a Coproduct [shapeless]
import shapeless._
@annotation.implicitNotFound("Make sure all cases of ${C} have an instance of ${TC}")
trait CopTCs[C <: Coproduct, TC[_]] {
type Out <: HList
def result: Out
}
object CopTCs {
type Aux[C <: Coproduct, TC[_], O <: HList] = CopTCs[C, TC] { type Out = O }
def apply[C <: Coproduct, TC[_]](implicit ev: CopTCs[C, TC]) = ev

Thread Pools

Thread pools on the JVM should usually be divided into the following three categories:

  1. CPU-bound
  2. Blocking IO
  3. Non-blocking IO polling

Each of these categories has a different optimal configuration and usage pattern.

Why not both?

With the recent announcement of cats-effect, a relevant question from the past resurfaces: why does IO, which is otherwise quite Task-like, not define both or race? To be clear, the type signatures of these functions would be as follows:

object IO {
  def both[A, B](ioa: IO[A], iob: IO[B])(implicit EC: ExecutionContext): IO[(A, B)] = ???
  def race[A, B](ioa: IO[A], iob: IO[B])(implicit EC: ExecutionContext): IO[Either[A, B]] = ???
}

Applied Functional Programming with Scala - Notes

Copyright © 2016-2018 Fantasyland Institute of Learning. All rights reserved.

1. Mastering Functions

A function is a mapping from one set, called a domain, to another set, called the codomain. A function associates every element in the domain with exactly one element in the codomain. In Scala, both domain and codomain are types.

val square : Int => Int = x => x * x
package cats.bench
import cats.data.Xor
import cats.instances.either._
import cats.syntax.all._
import org.openjdk.jmh.annotations.{ Benchmark, Scope, State }
@State(Scope.Benchmark)
class EitherBench {
val ea: Either[String, Int] = Right(1)
@tpolecat
tpolecat / listt.scala
Last active October 10, 2021 06:51
A demonstration in Scala of failed associativity of ListT. Example taken from https://wiki.haskell.org/ListT_done_right
// addCompilerPlugin("com.milessabin" % "si2712fix-plugin" % "1.2.0" cross CrossVersion.full)
import scalaz._, Scalaz._
implicit def f2k[F[_], A, B](f: A => F[B]) = Kleisli(f)
val a: Int => ListT[List, Int] = {
case 0 => ListT(List(List(0, 1)))
case 1 => ListT(List(List(0), List(1)))
}
@etorreborre
etorreborre / eff-match-result.scala
Last active April 24, 2016 21:27
Experiment using the Eff monad to test deeply nested structures
val e = Option(List(Right(2), Left("bad")))
runResult {
for {
as <- (e must beSome).opt
a <- fromList(as)
i <- (a must beRight).opt
_ <- (i must be_>(0)).check
} yield ()
}

Explaining Miles's Magic

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
@etorreborre
etorreborre / effForReal.scala
Last active September 7, 2016 03:22
Using Eff on a "real" use case
/**
* We need to create bidirectional maps for items having both a name an an id
* When we collect items, we need to check that there are no duplicated names or ids for a given item
*/
// first let's define bi-directional maps
case class BiMap[K, V](keys: Map[K, V], values: Map[V, K]) {
def add(entry: BiMapEntry[K, V]): BiMap[K, V] =
BiMap(keys + (entry.key -> entry.value), values + (entry.value -> entry.key))