Skip to content

Instantly share code, notes, and snippets.

View biboudis's full-sized avatar

Aggelos Biboudis biboudis

View GitHub Profile

Principled Meta Programming for Scala

This note outlines a principled way to meta-programming in Scala. It tries to combine the best ideas from LMS and Scala macros in a minimalistic design.

  • LMS: Types matter. Inputs, outputs and transformations should all be statically typed.

  • Macros: Quotations are ultimately more easy to deal with than implicit-based type-lifting

  • LMS: Some of the most interesting and powerful applications of meta-programming

Phantom types

Phantom types are designed to support compile time type evidences without any overhead costs to runtime. Phantom evidences are usually in the form of implicit arguments, which once resolved, can be erased by the compiler.

Because of these properties, phantom types are completely outside of the normal type lattice, and as such these phantom types do not inherit the semantics of Any.

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

@palladin
palladin / gist:6fac782a0ba4aa6b88b5
Last active September 25, 2021 17:51
Push/Pull Streams
type Stream<'T> = ('T -> unit) -> unit -> bool
let inline ofArray (source : 'T []) : Stream<'T> =
fun iterf ->
let i = ref 0
fun () ->
let flag = !i < source.Length
if not flag then
false
@raichoo
raichoo / gist:2a0e19140304bcc7d41a
Created September 18, 2014 23:18
Playing with co-patterns in Agda
{-# OPTIONS --copatterns #-}
module Test where
open import Data.Nat
open import Data.Bool
open import Data.Vec hiding (map; head; tail; take)
record Functor (F : Set → Set) : Set₁ where
field
map : ∀ {A B} → (A → B) → F A → F B
using NodaTime;
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace JITterOptimisations
{
public static class Extensions
@palladin
palladin / gist:c34a3a761f755b57244c
Created July 27, 2014 15:05
ParStream.sortBy performance test
#time
#r "bin/Release/Streams.Core.dll"
open Nessos.Streams.Core
let rnd = new System.Random()
let data = [|1..10000000|] |> Array.map (fun _ -> int64 <| rnd.Next(1000000))
#r "../../packages/FSharp.Collections.ParallelSeq.1.0/lib/net40/FSharp.Collections.ParallelSeq.dll"
open FSharp.Collections.ParallelSeq
@xeno-by
xeno-by / gist:5967900
Created July 10, 2013 16:38
Macro-powered structural types
import scala.annotation.StaticAnnotation
import scala.reflect.macros.Macro
import language.experimental.macros
class body(tree: Any) extends StaticAnnotation
trait Macros extends Macro {
import c.universe._
def selFieldImpl = {
scala> baseMap[List[Int]].kinds
res0: List[improving.Kind] = List(* -> *, (*, *) -> *, (*, * -> *) -> *, *)
scala> baseMap[List[Int]] ofKind (*, * -> *) -> * foreach println
scala.collection.generic.GenericTraversableTemplate[Int,List]
scala> baseMap[List[Int]] ofKind (*, *) -> * foreach println
scala.collection.LinearSeqOptimized[Int,List[Int]]
scala.collection.LinearSeqLike[Int,List[Int]]
@pthariensflame
pthariensflame / IndexedCont.md
Last active April 3, 2022 00:30
An introduction to the indexed continuation monad in Haskell, Scala, and C#.

The Indexed Continuation Monad in Haskell, Scala, and C#

The indexed state monad is not the only indexed monad out there; it's not even the only useful one. In this tutorial, we will explore another indexed monad, this time one that encapsulates the full power of delimited continuations: the indexed continuation monad.

Motivation

The relationship between the indexed and regular state monads holds true as well for the indexed and regular continuation monads, but while the indexed state monad allows us to keep a state while changing its type in a type-safe way, the indexed continuation monad allows us to manipulate delimited continuations while the return type of the continuation block changes arbitrarily. This, unlike the regular continuation monad, allows us the full power of delimited continuations in a dynamic language like Scheme while still remaining completely statically typed.