Skip to content

Instantly share code, notes, and snippets.

Avatar

Chris Birchall cb372

View GitHub Profile
View DTList.scala
import scala.compiletime.S
sealed trait DTList[N <: Int]:
inline def size: N = valueOf[N]
def +:[H](h: H): DTNonEmptyList[N, H, this.type] =
DTNonEmptyList(h, this)
case object DTNil extends DTList[0]
case class DTNonEmptyList[N <: Int, H, T <: DTList[N]](
@cb372
cb372 / io-and-tf.md
Last active May 22, 2021
IO and tagless final
View io-and-tf.md

TL;DR

We should use a type parameter with a context bound (e.g. F[_]: Sync) in library code so users can choose their IO monad, but we should use a concrete IO monad in application code.

Abstracting over IO

If you're writing a library that makes use of effects, it makes sense to use the cats-effect type classes so users can choose their IO monad (IO, ZIO, Monix Task, etc).

So instead of

@cb372
cb372 / sbtnew.sh
Last active Apr 4, 2019
Poor man's sbt template. Useful for quickly generating a throwaway sbt project when you just want to try something out.
View sbtnew.sh
# stick this in your .bashrc/.zshrc
sbtnew() {
local projectname=$1
local sbtversion=${2:-1.2.8}
local scalaversion=${3:-2.12.8}
cd ~/code
mkdir $projectname
cd $projectname
mkdir project
echo "sbt.version=$sbtversion" > project/build.properties
@cb372
cb372 / riscv.md
Last active Jun 15, 2021
Writing an OS in Rust to run on RISC-V
View riscv.md

(This is a translation of the original article in Japanese by moratorium08.)

(UPDATE (22/3/2019): Added some corrections provided by the original author.)

Writing your own OS to run on a handmade CPU is a pretty ambitious project, but I've managed to get it working pretty well so I'm going to write some notes about how I did it.

@cb372
cb372 / cross-account-peering-role.yml
Last active Jun 10, 2020
CloudFormation for setting up a VPC
View cross-account-peering-role.yml
AWSTemplateFormatVersion: 2010-09-09
Description: >
Creates a cross-account role that your AWS account can assume
in order to accept a VPC peering connection in the other account.
This is pretty confusing, so to clarify,
1. Run this CloudFormation in the OTHER account to create the cross-account role.
2. Your account requests a peering connection with the other account.
3. Your account assumes the role in order to access the other account
and accept the peering connection.
Parameters:
@cb372
cb372 / gist:66bc0ffdfec87744c473355a34ac61f3
Created Jan 3, 2019
Pushing commits to someone else's PR
View gist:66bc0ffdfec87744c473355a34ac61f3
# Terminology
their_username = the GitHub username of the contributor who submitted the PR
their_branch = the name of the branch they used to submit the PR
repo_name = the name of your GitHub repository
# First add their fork as a remote
git remote add $their_username git@github.com:${their_username}/${repo_name}.git
# Then fetch it
git fetch $their_username
@cb372
cb372 / authenticate.scala
Created Aug 24, 2018
Conditional caching in ScalaCache
View authenticate.scala
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scalacache._
import scalacache.caffeine._
import scalacache.modes.scalaFuture._
type Error = String
type Token = Int
View gitter.md

First of all, sorry for the radio silence. I forgot this channel existed, and Gitter notifications have always been flaky for me.

Second, it sounds like the reasons behind adding a type parameter to Cache are not very clear, so I'll explain below. Maybe I should add some kind of design/architecture page to the microsite?

Third, thank you for all your work on the PR. Sorry again for not being available to give feedback earlier.

@cb372
cb372 / .ctags
Created May 24, 2018
Neovim setup for Scala
View .ctags
--langdef=scala
--langmap=scala:.scala
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private[^ ]*|protected)?[ \t]*class[ \t]+([a-zA-Z0-9_]+)/\4/c,classes/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private[^ ]*|protected)?[ \t]*object[ \t]+([a-zA-Z0-9_]+)/\4/o,objects/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private[^ ]*|protected)?[ \t]*((abstract|final|sealed|implicit|lazy)[ \t ]*)*case class[ \t ]+([a-zA-Z0-9_]+)/\6/C,case classes/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private[^ ]*|protected)?[ \t]*case object[ \t]+([a-zA-Z0-9_]+)/\4/O,case objects/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy)[ \t]*)*(private[^ ]*|protected)?[ \t]*trait[ \t]+([a-zA-Z0-9_]+)/\4/t,traits/
--regex-scala=/^[ \t]*type[ \t]+([a-zA-Z0-9_]+)/\1/T,types/
--regex-scala=/^[ \t]*((abstract|final|sealed|implicit|lazy|override|private[^ ]*(\[[a-z]*\])*|protected)[ \t]*)*def[ \t]+([a-zA-Z0-9_]+)/\4/m,methods/
--re