Skip to content

Instantly share code, notes, and snippets.

View stephen-lazaro's full-sized avatar
🐬
Only quasicoherent

Stephen Lazaro stephen-lazaro

🐬
Only quasicoherent
View GitHub Profile
@stephen-lazaro
stephen-lazaro / ZModulo.scala
Last active June 19, 2019 17:39
Compile time checked modular arithmetic
package sl.persians
import eu.timepit.refined._
import eu.timepit.refined.api.Refined
import eu.timepit.refined.numeric.Interval
import shapeless.{Widen, Witness}
import singleton.ops.{>=, Require}
import spire.algebra.{CModule, CRing}
final class ZModulo[Upper] private[persians] (val value: Int) extends AnyVal
@stephen-lazaro
stephen-lazaro / naperian.scala
Created June 12, 2019 18:05
Naperian Functors
trait Naperian[F[_]] {
val F: Distributive[F]
def hdistribute[W[?[_], _]: HFunctor]: W[F, ?] ~> Nested[F, W[Id, ?], ?]
def ncotraverse[W[?[_], _]: HFunctor, A, B](f: W[Id, A] => B)(wf: W[F, A]): F[B] =
F.lift(f).apply(hdistribute[W].apply[A](wf).value)
def ncollect[W[?[_], _]: HFunctor, G[_]](f: G ~> F): W[G, ?] ~> Nested[F, W[Id, ?], ?] =
new (W[G, ?] ~> Nested[F, W[Id, ?], ?]) {
@stephen-lazaro
stephen-lazaro / alternatives_as_semirings.scala
Last active November 9, 2018 18:57
Lifting arbitrary semirings to alternatives via const...
trait Semiring[A] {
def zero: A
def plus(x: A, y: A): A
def one: A
def times(x: A, y: A): A
}
trait Alternative[F[_]] {
def pure[A](x: A): F[A]
def product[A, B](fa: F[A])(fb: F[B]): F[(A, B)]
trait Codensity[K[_], A] {
def run[B](f: A => K[B]): K[B]
}
object Codensity extends Low {
trait FunctorForCodensity[F[_]] extends Functor[Codensity[F, ?]] {
def map[A, BB](codensity: Codensity[F, A])(f: A => BB): Codensity[F, BB] =
new Codensity[F, BB] {
def run[B](g: BB => F[B]): F[B] =
codensity.run(f andThen g)
}

Keybase proof

I hereby claim:

  • I am stephen-lazaro on github.
  • I am stephenlazaro (https://keybase.io/stephenlazaro) on keybase.
  • I have a public key whose fingerprint is 6890 012A 882F B29E 3551 E746 37C9 2892 E6CE 6669

To claim this, I am signing this object:

import com.twitter.util.Future
object imp {
// Cats has a more fully featured version of this
// These are Future returning pure functions
type KleisliFuture [A, B] = A => Future [B]
// The actual implementation
implicit val futureKleisliCategory = new Category[KleisliFuture] {
def id [A] : KleisliFuture [A, A] = a => Future.value(a)
// This is JavaScript!
// Composition for Promise returning functions
// The identity is always:
const promiseIdentity = x => P.resolve(x);
// Composition is just `.then`!
const promiseCompose = f => g => x =>
g(x).then(f);
// This is standing for some complicated process
// Here we're using the Naturals type from Spire
import spire.math.{Natural => Nat}
object imp {
// Just faking out the type arguments required by compiler
// Const2 by any other name...
// A and B will always in practice be inferred as Nothing in practice
type AlwaysNats [A, B] = Nat
implicit val natsAreCats = new Category [AlwaysNats] {
def id [A] : AlwaysNats [A, A] = Nat(0)
trait Category [F [_, _]] {
// Has to fulfill compose (id [A], x: F [B, A]) = x: F [B, A]
// and on the opposite side
// compose (x: F [A, B], id [A]) = x: F[A, B]
def id [A]: F [A, A]
// Has to be associative!
// Notice also how the "middle type" B disappears in output here
def compose [A, B, C] (f: F [B, C], g: F [A, B]): F [A, C]
}
// This is JavaScript
// This is a bad compose utility for only one variable
const compose = f => g => x => f(g(x));
const cayleyNaturals = n => x => n + x;
// Look, nothing scary here
const add5 = cayleyNaturals(5);
const add6 = cayleyNaturals(6);
// Check this out:
const add11 = compose(add5)(add6)
// 🤔 this seems familiar