Skip to content

Instantly share code, notes, and snippets.

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

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
@sjednac
sjednac / SbtAmazonEcr.scala
Last active July 4, 2021 07:12
Pushing Docker images to Amazon ECR using an SBT plugin
object SbtAmazonEcr extends App {
while(true) {
println("Hello Docker.")
Thread.sleep(3000)
}
}
@paulp
paulp / global.sbt
Last active October 16, 2018 19:09
continuous compilation of the sbt build
// These lines go in ~/.sbt/0.13/global.sbt
watchSources ++= (
(baseDirectory.value * "*.sbt").get
++ (baseDirectory.value / "project" * "*.scala").get
++ (baseDirectory.value / "project" * "*.sbt").get
)
addCommandAlias("rtu", "; reload ; test:update")
addCommandAlias("rtc", "; reload ; test:compile")
addCommandAlias("ru", "; reload ; update")
@Fristi
Fristi / Data.scala
Last active July 26, 2017 09:21
Types are data and data are types
package data
import cats.Cartesian
import cats.data.{NonEmptyList, State, StateT, Validated}
import cats.functor.Invariant
import cats.implicits._
import eu.timepit.refined._
import eu.timepit.refined.api.{Refined, Validate}
import eu.timepit.refined.boolean._
import eu.timepit.refined.collection._

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

@lamdor
lamdor / build.sbt
Last active May 26, 2021 21:27
Playing around with tagless final style and Eff (from https://github.com/edmundnoble/final-tagless-typelevel-summit)
scalaVersion := "2.11.8"
scalaOrganization := "org.typelevel"
libraryDependencies ++= Seq(
"org.typelevel" %% "cats" % "0.9.0",
"org.atnos" %% "eff" % "4.0.0"
)
addCompilerPlugin("org.spire-math" %% "kind-projector" % "0.9.3")
sealed trait Decidable[+Proof]
final case class Yes[Proof](proof: Proof) extends Decidable[Proof]
final case object No extends Decidable[Nothing]
sealed trait List[+A] {
def nonEmpty: Decidable[this.type <:< ::[A]]
def ::[AA >: A](value: AA): ::[AA] = new ::[AA](value, this)
}
final case object Nil extends List[Nothing] {
def nonEmpty: Decidable[this.type <:< ::[Nothing]] = No
@johnynek
johnynek / flatMapFromTailRec.scala
Created October 7, 2017 01:55
I hadn't realized (maybe the original paper mentioned) but tailRecM + map is enough to do flatMap (and of course logically flatMap + pure are enough to do tailRecM).
object Monad {
trait Monad[F[_]] {
def pure[A](a: A): F[A]
/**
* We can have a default implementation in terms of tailRecM
* and map
*/
def flatMap[A, B](fa: F[A])(fn: A => F[B]): F[B] = {
def step(first: Option[A]): F[Either[Option[A], B]] =