#!/bin/bash | |
inner() { | |
local cmd="$@" | |
local REGEX="(^|log.showSignature=false )(add|rm|mv) " | |
if [[ $cmd =~ $REGEX ]]; then | |
echo 'Stopping IntelliJ from being a not well-behaved git client. See IDEA-194592, IDEA-63391, IDEA-176961, ...' >&2 | |
return 1 | |
fi | |
git "$@" | |
} |
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
A primer/refresher on the category theory concepts that most commonly crop up in conversations about Scala or FP. (Because it's embarassing when I forget this stuff!)
I'll be assuming Scalaz imports in code samples, and some of the code may be pseudo-Scala.
A functor is something that supports map
.
Kris Nuttycombe asks:
I genuinely wish I understood the appeal of unityped languages better. Can someone who really knows both well-typed and unityped explain?
I think the terms well-typed and unityped are a bit of question-begging here (you might as well say good-typed versus bad-typed), so instead I will say statically-typed and dynamically-typed.
I'm going to approach this article using Scala to stand-in for static typing and Python for dynamic typing. I feel like I am credibly proficient both languages: I don't currently write a lot of Python, but I still have affection for the language, and have probably written hundreds of thousands of lines of Python code over the years.
package p { | |
trait Functor[F[X]] extends Any { def fmap[A, B](x: A => B): F[A] => F[B] } | |
trait Pointed[F[X]] extends Functor[F] { def pure[A](x: A): F[A] } | |
trait Monad[F[X]] extends Pointed[F] { def join[A](x: F[F[A]]): F[A] } | |
trait Copointed[F[X]] extends Functor[F] { def copure[A](x: F[A]): A } | |
trait Comonad[F[X]] extends Copointed[F] { def cojoin[A](x: F[A]): F[F[A]] } | |
trait Bimonad[F[X]] extends Monad[F] with Comonad[F] | |
sealed trait Monadic[F[X], A] extends Any | |
final case class Pure[F[X], A](x: A) extends Monadic[F, A] |
object TransducerUniversal { | |
type Reduct[-A, R] = (R, A) => R | |
trait Trans[+A, -B] { def apply[R](f: Reduct[A, R]): Reduct[B, R] } | |
def map[A, B](f: A => B): Trans[B, A] = new Trans[B, A] { def apply[R](rf: Reduct[B, R]) = (r, a) => rf(r, f(a)) } | |
def filter[A](p: A => Boolean): Trans[A, A] = new Trans[A, A] { def apply[R](rf: Reduct[A, R]) = (r, a) => if (p(a)) rf(r, a) else r } | |
def comp[A,B,C](t1 : Trans[A, B], t2 : Trans[C, A]): Trans[C, B] = new Trans[C, B] { def apply[R](rf: Reduct[C, R]) = t1(t2(rf)) } | |
def sequence[A, B](t: Trans[B, A], data: Seq[A]) = data.foldLeft(Seq[B]())(t(_ :+ _)) | |
implicit class Compable[A,B](t1: Trans[A, B]) { |
def toCamelCase(String string) { | |
String result = "" | |
string.findAll("[^\\W]+") { String word -> | |
result += word.capitalize() | |
} | |
return result | |
} | |
afterEvaluate { project -> | |
Configuration runtimeConfiguration = project.configurations.getByName('compile') |