Skip to content

Instantly share code, notes, and snippets.

View akhileshs's full-sized avatar

Akhilesh Srikanth akhileshs

  • San Francisco, CA
View GitHub Profile
@tonymorris
tonymorris / ttg.hs
Last active January 28, 2019 09:30
Trees That Grow
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE StandaloneDeriving #-}

Quick Tips for Fast Code on the JVM

I was talking to a coworker recently about general techniques that almost always form the core of any effort to write very fast, down-to-the-metal hot path code on the JVM, and they pointed out that there really isn't a particularly good place to go for this information. It occurred to me that, really, I had more or less picked up all of it by word of mouth and experience, and there just aren't any good reference sources on the topic. So… here's my word of mouth.

This is by no means a comprehensive gist. It's also important to understand that the techniques that I outline in here are not 100% absolute either. Performance on the JVM is an incredibly complicated subject, and while there are rules that almost always hold true, the "almost" remains very salient. Also, for many or even most applications, there will be other techniques that I'm not mentioning which will have a greater impact. JMH, Java Flight Recorder, and a good profiler are your very best friend! Mea

;; try this form-by-form at a REPL
(require '[clojure.spec.alpha :as s])
;; create an inline DSL to describe the FizzBuzz world
(defmacro divides-by
[nm n]
`(s/def ~nm (s/and pos-int? #(zero? (mod % ~n)))))
;; specify FizzBuzz
(divides-by ::fizz 3)
@dorchard
dorchard / Category.agda
Last active August 17, 2017 14:13
Definition of a category as an Agda record: level polymorphic in the objects and arrows
module Category where
open import Level
open import Relation.Binary.PropositionalEquality
open Level
record Category {lobj : Level} {larr : Level} : Set (suc (lobj ⊔ larr)) where
field obj : Set lobj
arr : (src : obj) -> (trg : obj) -> Set larr
@kritzcreek
kritzcreek / random-numbers.md
Last active May 24, 2021 18:36
Collections of random numbers in PureScript

Generating collections of random numbers in PureScript

A problem that I've seen beginners run into in Haskell or PureScript a couple of times now is how to generate a List of random numbers. It's a common requirement for little games (which make for great first projects) to generate these, and it definitely seems to be a stumbling block.

Why are random numbers hard?

Randomness is considered a side effect in purely functional languages, which means that to generate them you usually need access to Eff/IO, which in turn means we need to deal with Monads. And while generating a single random number is usually pretty easy with do-notation, the typical intuition beginners have built when going from single values to a collection is to use map, but that fails.

Type-Directed-Search to the rescue

@kritzcreek
kritzcreek / Kinds-and-do-syntax.md
Last active March 28, 2020 11:51
Kinds and Do-Syntax

Kinds

In PureScript there are types of different kinds. Kinds are types for types. For example Int has kind Type, and we write it as Int :: Type. You can ask for the kind of a type in purs psci

> :k Int
Type

Type constructors take types to other types. For example Array (which still needs another type to form a type a value could have, like Array Int):

import sbt._, Keys._
import scala.xml.{Node => XmlNode, NodeSeq => XmlNodeSeq, _}
import scala.xml.transform.{RewriteRule, RuleTransformer}
import sbt.plugins.JvmPlugin
object PPrintPlugin extends AutoPlugin {
override def requires = JvmPlugin
override def trigger: PluginTrigger = AllRequirements
override def projectSettings: Seq[Def.Setting[_]] = List(
libraryDependencies ++= {
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
@aaronlevin
aaronlevin / cats-mtl.scala
Last active May 26, 2017 17:38
Does the cats-mtl design support for-comprehensions with multiple Monad constraints? Looks like it does!
package cats
import cats.data.{StateT, WriterT}
import cats.implicits._
/**
* TypeLevel is working on some alternative encodings of the Monad Transformer
* Library (MTL). The existing solution in cats was broken for a few reasons.
* One annoying issue made it imposisible to use for-comprehension with more
* than one Monad$FOO constraint owing to implicit resolution ambiguities.
@sjrd
sjrd / WithGlobals.scala
Created April 30, 2017 22:20
I wrote a monad
/* __ *\
** ________ ___ / / ___ __ ____ Scala.js tools **
** / __/ __// _ | / / / _ | __ / // __/ (c) 2013-2017, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ **
** /____/\___/_/ |_/____/_/ | |__/ /____/ **
** |/____/ **
\* */
package org.scalajs.core.tools.linker.backend.emitter