About

Hi, I'm Jay.

In 2018 I started working full time as a software developer. This gave me some time to think about how I might try to give back to the software development community.

I'm hoping to write about my experiences in the software industry, problems I've faced with tools and solutions/hacks that I've discovered (or been gifted) along the way as well as a few interesting algorithms that I've learnt a bit about.

I have a particular interest in 'safe' languages, machine learning, and logic engines. Specifically I'm a big fan of Haskell and Rust, but have more experience in C++ and Python.

I live in Sydney with my lovely wife and Peanut, our Japanese Spitz. They mean everything to me.


A view of Mount Kosciuszko

Kosciuszko National Park

WIP - Work in progress

The following post is a work in progress, but I thought I'd keep uploading it as a way to push myself to finish it sooner rather than later.

Lambda Calculus: Building little languages

In my work I have had several opportunities to build tooling for other developers. Specifically these have been tools for assembling apps, programs and infrastructure using a high level language.

These have mostly been experimental, either exploring the benefits of different compiler architectures, approaches to optimisation or programming paradigms.

So, I've been stuck with a question:

How do we build a programming language from the smallest number of the simplest parts possible?

Many approaches have been taken to building programming languages and compilers, and there are almost as many approaches to doing so.

A small family tree of programming language models

My favourite approach: Lambda Calculus

My favourite class of approaches is to build a small core language and build everything on top of that. This has a few benefits that I hope to detail here.

TODO: Finish

#![allow(unused)]
fn main() {
#[derive(Debug, Clone, Eq, Hash, Ord, PartialOrd, PartialEq)]
enum Term {
    Var(usize),
    App(Box<Term>, Box<Term>),
    Abs(Box<Term>),
}

fn abs(t: Term) -> Term {
    Term::Abs(Box::new(t))
}

fn app(t: Term, a: Term) -> Term {
    Term::App(Box::new(t), Box::new(a))
}

fn var(i: usize) -> Term {
    Term::Var(i)
}

let a_b_gives_a = abs(abs(var(0)));
let a_b_gives_b = abs(abs(var(1)));
println!("A simple term {:?}", a_b_gives_a);
println!("Another simple term {:?}", a_b_gives_b);

fn render(term: &Term) -> String {
    format!("{:?}", term)
}

}
#![allow(unused)]
fn main() {
#[derive(Debug, Clone, Eq, Hash, Ord, PartialOrd, PartialEq)]
enum Term {
    Var(usize),
    App(Box<Term>, Box<Term>),
    Abs(Box<Term>),
}

fn abs(t: Term) -> Term {
    Term::Abs(Box::new(t))
}

fn app(t: Term, a: Term) -> Term {
    Term::App(Box::new(t), Box::new(a))
}

fn var(i: usize) -> Term {
    Term::Var(i)
}

let a_b_gives_a = abs(abs(var(0)));
let a_b_gives_b = abs(abs(var(1)));
println!("A simple term {:?}", a_b_gives_a);
println!("Another simple term {:?}", a_b_gives_b);

fn render(term: &Term) -> String {
    format!("{:?}", term)
}

}
#![allow(unused)]
fn main() {
#[derive(Debug, Clone, Eq, Hash, Ord, PartialOrd, PartialEq)]
enum Term {
    Var(usize),
    App(Box<Term>, Box<Term>),
    Abs(Box<Term>),
}

fn abs(t: Term) -> Term {
    Term::Abs(Box::new(t))
}

fn app(t: Term, a: Term) -> Term {
    Term::App(Box::new(t), Box::new(a))
}

fn var(i: usize) -> Term {
    Term::Var(i)
}

let a_b_gives_a = abs(abs(var(0)));
let a_b_gives_b = abs(abs(var(1)));
println!("A simple term {:?}", a_b_gives_a);
println!("Another simple term {:?}", a_b_gives_b);

fn render(term: &Term) -> String {
    format!("{:?}", term)
}

}

Fin


Here's the full code for you to experiment with:

#[derive(Debug, Clone, Eq, Hash, Ord, PartialOrd, PartialEq)]
enum Term {
    Var(usize),
    App(Box<Term>, Box<Term>),
    Abs(Box<Term>),
}

fn abs(t: Term) -> Term {
    Term::Abs(Box::new(t))
}

fn app(t: Term, a: Term) -> Term {
    Term::App(Box::new(t), Box::new(a))
}

fn var(i: usize) -> Term {
    Term::Var(i)
}

let a_b_gives_a = abs(abs(var(0)));
let a_b_gives_b = abs(abs(var(1)));
println!("A simple term {:?}", a_b_gives_a);
println!("Another simple term {:?}", a_b_gives_b);

fn render(term: &Term) -> String {
    format!("{:?}", term)
}

WIP - Work in progress

The following post is a work in progress, but I thought I'd keep uploading it as a way to push myself to finish it sooner rather than later.

Lambda Calculus: Building little languages

In my work I have had several opportunities to build tooling for other developers. Specifically these have been tools for assembling apps, programs and infrastructure using a high level language.

These have mostly been experimental, either exploring the benefits of different compiler architectures, approaches to optimisation or programming paradigms.

So, I've been stuck with a question:

How do we build a programming language from the smallest number of the simplest parts possible?

Many approaches have been taken to building programming languages and compilers, and there are almost as many approaches to doing so.

A small family tree of programming language models

My favourite approach: Lambda Calculus

My favourite class of approaches is to build a small core language and build everything on top of that. This has a few benefits that I hope to detail here.

TODO: Finish

#![allow(unused)]
fn main() {
#[derive(Debug, Clone, Eq, Hash, Ord, PartialOrd, PartialEq)]
enum Term {
    Var(usize),
    App(Box<Term>, Box<Term>),
    Abs(Box<Term>),
}

fn abs(t: Term) -> Term {
    Term::Abs(Box::new(t))
}

fn app(t: Term, a: Term) -> Term {
    Term::App(Box::new(t), Box::new(a))
}

fn var(i: usize) -> Term {
    Term::Var(i)
}

let a_b_gives_a = abs(abs(var(0)));
let a_b_gives_b = abs(abs(var(1)));
println!("A simple term {:?}", a_b_gives_a);
println!("Another simple term {:?}", a_b_gives_b);

fn render(term: &Term) -> String {
    format!("{:?}", term)
}

}
#![allow(unused)]
fn main() {
#[derive(Debug, Clone, Eq, Hash, Ord, PartialOrd, PartialEq)]
enum Term {
    Var(usize),
    App(Box<Term>, Box<Term>),
    Abs(Box<Term>),
}

fn abs(t: Term) -> Term {
    Term::Abs(Box::new(t))
}

fn app(t: Term, a: Term) -> Term {
    Term::App(Box::new(t), Box::new(a))
}

fn var(i: usize) -> Term {
    Term::Var(i)
}

let a_b_gives_a = abs(abs(var(0)));
let a_b_gives_b = abs(abs(var(1)));
println!("A simple term {:?}", a_b_gives_a);
println!("Another simple term {:?}", a_b_gives_b);

fn render(term: &Term) -> String {
    format!("{:?}", term)
}

}
#![allow(unused)]
fn main() {
#[derive(Debug, Clone, Eq, Hash, Ord, PartialOrd, PartialEq)]
enum Term {
    Var(usize),
    App(Box<Term>, Box<Term>),
    Abs(Box<Term>),
}

fn abs(t: Term) -> Term {
    Term::Abs(Box::new(t))
}

fn app(t: Term, a: Term) -> Term {
    Term::App(Box::new(t), Box::new(a))
}

fn var(i: usize) -> Term {
    Term::Var(i)
}

let a_b_gives_a = abs(abs(var(0)));
let a_b_gives_b = abs(abs(var(1)));
println!("A simple term {:?}", a_b_gives_a);
println!("Another simple term {:?}", a_b_gives_b);

fn render(term: &Term) -> String {
    format!("{:?}", term)
}

}

Fin


Here's the full code for you to experiment with:

#[derive(Debug, Clone, Eq, Hash, Ord, PartialOrd, PartialEq)]
enum Term {
    Var(usize),
    App(Box<Term>, Box<Term>),
    Abs(Box<Term>),
}

fn abs(t: Term) -> Term {
    Term::Abs(Box::new(t))
}

fn app(t: Term, a: Term) -> Term {
    Term::App(Box::new(t), Box::new(a))
}

fn var(i: usize) -> Term {
    Term::Var(i)
}

let a_b_gives_a = abs(abs(var(0)));
let a_b_gives_b = abs(abs(var(1)));
println!("A simple term {:?}", a_b_gives_a);
println!("Another simple term {:?}", a_b_gives_b);

fn render(term: &Term) -> String {
    format!("{:?}", term)
}

Hi, I'm Jay. I write software for a living and actually really enjoy it. Well, most of the time.

I keep finding myself wanting to write up some of the things I've learnt about and the mistakes I've made. So here we are. Hopefully someone can learn from it and possibly avoid the same issues that I had.

My first post will just cover some of the steps I took to set this site up as a bit of a walk through. If you're not wanting to build a site today feel free to look through it anyway. I'm hoping to follow up with some tips on using Git, Shell (in particular zsh) but for now I'll try to keep it brief.

It'll be far easier if you already use a terminal regularly and are familiar with Git but I'll try to introduce things as they come up.

What are we using?

First up, I want to thank David Darnes who make the Alembic theme. That theme is responsible for the majority of the styling (and a significant portion of the functionality) of the site. He did an awesome job and even included some really nice features like a service worker, RSS feed, and search and contact pages.

I plan to tweak it further to suit my needs but the theme is a lovely collection of useful templates and CSS and is easy to install and use.

For hosting, I'm using Github Pages, a very neat static site tool built by and integrated with Github. It takes a bunch of configuration files and pages written in Markdown and turns them into a site that runs on $USERNAME.github.io for free.

P.S. I'm going to use this notation to show that I mean a command that can be run in your terminal and $this_notation to show that the value might not be the same for everyone and should be something you set up or something already available in your shell.

Steps

1. Get a Github account or use one that you already have.

Sign up at https://github.com/ (or you can use other hosts for git and your site if you are already familiar with them).

2. Create a new repository called $USERNAME.github.io.

  • Use https://github.com/new if you're using Github.
  • Call it $USERNAME.github.io (a special repository name that tells github that you want to use it as a github pages site.

3. Install 'git'

Git is a really useful tool for managing (mostly text) files that change over time while also being edited by multiple people. It's a pretty complex piece of software so I'll point you to some other tutorials about it.

Here's some to get git installed on a few common platforms:

4. Install ruby, bundler, jekyll, an editor etc.

There's an official quite start guide to jekyll here but I'll add a tldr.

  • Linux: Again for linux users either you can probably use apt install ruby (or you proabably know how to install packages yourself).

  • Mac: Similar to linux brew install ruby

  • Windows users can use rubyinstaller but I can't promise that it works particularly well.

Now that we all have ruby, we can use it's package manager (gem) to install jekyll (and bundler) tools for running the site: gem install jekyll bundler.

5. Create a new Jekyll site

Now it's time to build a skeleton for your site. You can use a template online (I used the Alembic theme) or use jekyll new $USERNAME.github.io to make a completely clean new site.

  • cd $USERNAME.github.io

6. Set up your repo.

  • Turn the jekyll site into a git repo.
    • git init
  • Add a 'remote'
    • git remote add git@github.com:$USERNAME/$USERNAME.github.io.git
  • Push your code up to github for the first time!
    • git push -u origin master

7. Try it locally

The command that we are going to use to run the site locally is: jekyll server --livereload

This tells jekyll the program that builds the site to run a server locally (it should be on localhost:4000. The --livereload flag tells jekyll to reload the site when the source files change. This makes it easy to modify the site quickly and see what the outcome is.

If you're looking around for things to change try looking in ./_posts,

Any theme styling is in ./_sass and some config in ./_config and there's loads to play around with before it's 'production ready' but hopefully this gets you started.

8. Try it online

When you're ready you can commit your changes to your git remote and then git push them up to your server.

Now your $USERNAME.github.io should be live with your site.

I'm working on a follow up on this post that talks more about the specifics about jekyll that surprised me. See you soon.


Hi, I'm Jay. I write software for a living and actually really enjoy it. Well, most of the time.

I keep finding myself wanting to write up some of the things I've learnt about and the mistakes I've made. So here we are. Hopefully someone can learn from it and possibly avoid the same issues that I had.

My first post will just cover some of the steps I took to set this site up as a bit of a walk through. If you're not wanting to build a site today feel free to look through it anyway. I'm hoping to follow up with some tips on using Git, Shell (in particular zsh) but for now I'll try to keep it brief.

It'll be far easier if you already use a terminal regularly and are familiar with Git but I'll try to introduce things as they come up.

What are we using?

First up, I want to thank David Darnes who make the Alembic theme. That theme is responsible for the majority of the styling (and a significant portion of the functionality) of the site. He did an awesome job and even included some really nice features like a service worker, RSS feed, and search and contact pages.

I plan to tweak it further to suit my needs but the theme is a lovely collection of useful templates and CSS and is easy to install and use.

For hosting, I'm using Github Pages, a very neat static site tool built by and integrated with Github. It takes a bunch of configuration files and pages written in Markdown and turns them into a site that runs on $USERNAME.github.io for free.

P.S. I'm going to use this notation to show that I mean a command that can be run in your terminal and $this_notation to show that the value might not be the same for everyone and should be something you set up or something already available in your shell.

Steps

1. Get a Github account or use one that you already have.

Sign up at https://github.com/ (or you can use other hosts for git and your site if you are already familiar with them).

2. Create a new repository called $USERNAME.github.io.

  • Use https://github.com/new if you're using Github.
  • Call it $USERNAME.github.io (a special repository name that tells github that you want to use it as a github pages site.

3. Install 'git'

Git is a really useful tool for managing (mostly text) files that change over time while also being edited by multiple people. It's a pretty complex piece of software so I'll point you to some other tutorials about it.

Here's some to get git installed on a few common platforms:

4. Install ruby, bundler, jekyll, an editor etc.

There's an official quite start guide to jekyll here but I'll add a tldr.

  • Linux: Again for linux users either you can probably use apt install ruby (or you proabably know how to install packages yourself).

  • Mac: Similar to linux brew install ruby

  • Windows users can use rubyinstaller but I can't promise that it works particularly well.

Now that we all have ruby, we can use it's package manager (gem) to install jekyll (and bundler) tools for running the site: gem install jekyll bundler.

5. Create a new Jekyll site

Now it's time to build a skeleton for your site. You can use a template online (I used the Alembic theme) or use jekyll new $USERNAME.github.io to make a completely clean new site.

  • cd $USERNAME.github.io

6. Set up your repo.

  • Turn the jekyll site into a git repo.
    • git init
  • Add a 'remote'
    • git remote add git@github.com:$USERNAME/$USERNAME.github.io.git
  • Push your code up to github for the first time!
    • git push -u origin master

7. Try it locally

The command that we are going to use to run the site locally is: jekyll server --livereload

This tells jekyll the program that builds the site to run a server locally (it should be on localhost:4000. The --livereload flag tells jekyll to reload the site when the source files change. This makes it easy to modify the site quickly and see what the outcome is.

If you're looking around for things to change try looking in ./_posts,

Any theme styling is in ./_sass and some config in ./_config and there's loads to play around with before it's 'production ready' but hopefully this gets you started.

8. Try it online

When you're ready you can commit your changes to your git remote and then git push them up to your server.

Now your $USERNAME.github.io should be live with your site.

I'm working on a follow up on this post that talks more about the specifics about jekyll that surprised me. See you soon.


A really neat explanation of some approaches to references in Rust.

https://bryce.fisher-fleig.org/blog/strategies-for-returning-references-in-rust/index.html

I've been trying to get my head around the borrowing semantics of Rust. I'm really interested in the possibility of improving the state of memory usage in pure languages like Haskell with linear types and while I understand that some believe that the problem is better solved with regions based management I think Rust has a pretty nice system.

I hope to write a bit more on linear types, regions and Rust when I understand them better.


I wanted to make a first post about how to set up Jekyll, but it turns out that doing that without talking about Git is hard... and I am not yet ready to blog about git.

So, I hope that the following is useful.

I started using vim in Uni, having previously been happy with IDEs specialised to different (fairly specific) use cases and had avoided (and frankly, not even heard of) the popular 'hackers editors': emacs, vim and gedit (I'm almost kidding, but I do actually like Gedit). I'm so glad that I invested some time into learning vim as I think it's saved me a lot more, and also feels nicer to use that the other editors that I have experience with.

Plugin managers

First up, I find that having a plugin manager saves a tonne of time. Between Plug, Vundle, Pathogen and dein there's a lot of very good options, but personally I recommend Plug. I think it's the simplest and love that it runs asynchronously.

Colours || Colors

I find colour helps me to identify when I've messed up some syntax, misspelled a keyword or otherwise made a mistake.

For colour schemes I have to recommend badwolf which plays nicely with all my syntax highlighting plugins and Nvim a Vim fork that I really like. Here's how to install it:

Plugin
call plug#begin('~/.local/share/nvim/plugged') " Plugins go here
Plug 'sjl/badwolf'
call plug#end()

colorscheme badwolf

And then run :PlugInstall.

I'd also recommend that you use the following if you don't already:

syntax enable
set background=dark

This will turn on syntax highlighting and use a dark background (which I think has been minimizing the degradation of my eyesight).

Vim Tweaks

Have you ever edited a file, closed vim and then realised that the last thing you did wasn't so perfect, only to be unable to undo it easily? Version control helps, but isn't fine grained enough for my liking.

Fortunately, vim has a solution.

set undofile undodir=~/.config/nvim/undo-dir

undofile is the option to tell vim to store the edit history of the files you're working on. This means that when you start vim again, it'll load up all the recent changes you've made and let you undo them. This can be a super power when you add simnalamburt's Vim-mundo, a tool for showing your edit history as a tree, which makes it a lot easier to find a previous state of a file. The undodir is the file that it stores the history in, which you can put anywhere but I keep in my nvim config directory.

Write as sudo

Sometimes I edit a file only to discover that it's read only. I could quit, reopen the file with visudo or sudoedit but this is easier. p.s. You should probably be careful with sudo vim.

cmap w!! w !sudo tee > /dev/null %

This maps :w!! to write via a program called tee which lets you more safely write to files as root.

I believe this tip may have been from this post by jovica but honestly I have no idea if this is where I found out about it.

Some plugins

tmhedberg's Matchit

This improves vim 'find next matching bracket' functionality (by default mapped to '%'). Normally, it can match brackets in C like languages but the plugin expands it to be able to find matching tags in more complex formats like html and vim.

tpope's vim-enuch

This adds a bunch of great commands to do 'unixy' things like moving, renaming and deleting files. Seriously it's amazing and includes some nice file search tools. Tpope has a bunch of other great plugins too and is the maintainer of pathogen. He even wrote a plugin for writing plugins... .

roxma's vim-window-resize-easy

Beautiful in it's relative simplicity, this makes vim splits easy to manage without resorting to dragging their edges around.

junegunn's fzf

Fzf is amazing. It is a fuzzy finder that makes finding files in large projects or just on your computer much easier. I highly recommend you install it for your terminal, editor and really anything you can get to support it. Installation was actually a little finicky for me but here's the vim config needed for Plug.

Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }
Plug 'junegunn/fzf.vim'

AndrewRadev's switch

Provides :Switch which lets you switch statements like 'true' to 'false'. It supports a bunch more common replacements which will save you rewriting things (and more importantly, typos) and is even configurable. Here's my config for it.

Plug 'AndrewRadev/switch.vim'

...

let g:switch_custom_definitions =
    \ [
    \   ['0', '1'],
    \   ['[', ']', '(', ')', '{', '}'],
    \   ['TRUE', 'FALSE'],
    \   ['T', 'F'],
    \   ['.cc', '.h'],
    \ ]

nnoremap <leader>! :Switch<CR>

A final tip: Line 'shoving'

"Shove down: <A-j>
nnoremap ∆ :m.+1<CR>==
nnoremap <A-j> :m .+1<CR>==
inoremap <A-j> <Esc>:m .+1<CR>==gi
"Shove up: <A-k>
nnoremap ˚ :m .-2<CR>==
nnoremap <A-k> :m .-2<CR>==
inoremap <A-k> <Esc>:m .-2<CR>==gi

This maps Alt+j and Alt+k to swapping the current line with the line above or below it (the cursor moves with it). Useful for moving around debugging statements, re-ordering lists etc. The ∆ and ˚ are there because my Mac keyboard uses alt for inputting special characters and I like being able to write ∂x, but I also want the mapping consistent between my computers.


There we go. I have a fair bit more vim config, some of it I don't use and should clean up but mostly it's pretty helpful stuff that I think makes my life better.

Here's my current config, please don't copy paste without learning about what each part does (it'll make life harder when something goes wrong and you might miss out on some of the nice bits).

init.vim

Note: I haven't made any effort to make it vim compatible, or even particularly backwards compatible for older versions of neovim. Use with care.

Computers have gotten smarter over time, a lot smarter. You've probably heard of Moore's law. It's hard to appreciate the vast amount of RAM our modern laptops and phones have in comparison to earlier computer.

The original Apollo guidance computer had 2048 words of RAM. Each word is 16 bits, bringing the total RAM to 4kb.

It was used in the Apollo program to plan the route of the Command & Service module and Lunar Module (citation) and was an amazing piece of kit at the time (1966 - 1975).

These days, few popular web pages can fit in 4kb. I don't think that's a bad thing, though it gives us some room for improvement. It's just a part of the cost of all the improvements that we have made.

It turns out that there's still a lot that can be done in just a few kilobytes and there are a bunch of competitions that are centered around this. The most famous of which (that I know of) being the js1k competition.

The aim is simple:

Make a game in JavaScript that fits in 1 kilobyte!

You can minify, compress, use terse style, anything, as long as it fits in 1kilobyte.

The js1k competitors are pretty amazing, I recommend playing a few of their games (they download really quickly too).

1kb is pretty restrictive, and I was (and am) pretty new to code golfing, so I have yet to try the 1kb variety. However, a friend of mine is a pretty awesome web developer and invited me to compete with him in the js13k competition. It's basically the same as the js1k games... but as you can probably guess, you get 13kb.

JS 13k Games logo

So, with 13kb to play with we could implement almost anything we liked, and definitely more things that we had time for writing from scratch.

Lost Caves game screenshot

Here's our entry on js13kgames.com

And here's Sam's site.


I recently wrote something like the following Haskell:

divOrFail :: Either Int String -> Int -> Either Int String
divOrFail (Left d) n
  | n==0 = Right ("Cannot divide by 0")
  | (d`mod`n)/=0 = Right ("Cannot divide "++show d++" by "++show n)
  | otherwise = Left $ d`div`n
divOrFail (Right e) _ = (Right e)

applyAll :: Foldable f => (Either a err -> b -> Either a err) -> a -> f b -> Either a err
applyAll func start xs = foldl func (Left start) xs

The original was a bit more complicated but this preserves the bug in the original. So lets break this down a bit (or skip it if you like).

Lets start with the more complicated part. In particular this type signature:

applyAll :: Foldable f => (Either a err -> b -> Either a err) -> a -> f b -> Either a err

So, first ignore the type constraints (the Foldable f => bit) we can come back to it. Our arguments are:

  • a function that takes something of type b and either an a value or an error,
  • a start value
  • a thing holding things of type b (looking at the constraint, we can see that the 'bunch' is foldable which lets us do some neat stuff on it).

applyAll then uses foldl to repeatedly apply a function on a value (or an error), accumulating the result.

applyAll func start xs = foldl func (Left start) xs

So, that was all 'simple'. What could go wrong? /s

The other part of the code snippet is fairly straightforward:

divOrFail :: Int -> Either Int String -> Either Int String

This is a function that takes two things:

  • an Int
  • something that is either an Int or a String
divOrFail n (Left d)
  | n==0 = Right ("div by 0")
  | (d`mod`n)/=0 = Right ("Cannot divide "++show d++" by "++show n)
  | otherwise = Left $ d`div`n

When the 'something' is an Int that is a multiple of n we divide it by n and return the result. If it is not divisible, we return a 'Right' containing an error message of the form (e.g. 'Cannot divide 3 by 2') which tells the user that the number wasn't able to be divided.

divOrFail _ (Right e) = (Right e) When the 'something' is a string, we return the string (e.g. an error message).

This allows me to write things like:

> applyAll divOrFail 120 [1,2,3]
Left 20
> 1*2*3*20 == 120
True
> applyAll divOrFail 13 [3,0,1]
Right "Cannot divide by 0"
> applyAll divOrFail 12 [3,4,2]
Right "Cannot divide 1 by 2"

Hopefully it's clear now that this could be handy (even though it is just a toy example).

The catch

So, this is pretty good, right?

Well, not quite. See, I made a simple (foolish) mistake when I used this function.

Unfortunately I didn't write:

applyAll divOrFail 13 [3,0,1]

I wrote:

applyAll divOrFail 13 (Left [3,0,1])

Now this seems like it will error as Either [Int] b is a different type to [Int], but it doesn't. Let's check the types involved in ghci:

> :t [3,0,1]
[3,0,1] :: Num a => [a]

> :t Left [3,0,1]
Left [3,0,1] :: Num a => Either [a] b

So, we might have expected the types [a] and Either [a] b to be too different to fit in the same 'hole' (I did when I first found my bug).

But what does ghci say when I ask for the type (without the problematic argument)?

> :t applyAll divOrFail 13
applyAll divOrFail 13 :: Foldable f => f Int -> Either Int String

I'd never restricted the type to a list making applyAll divOrFail a polymorphic function. In fact, applyAll divOrFail could take any foldable over Ints. A lot of different data types implement Foldable, most of the 'container' types (e.g. List, Set, Map) have a Foldable instance. So this tells us that Either [a] has a Foldable instance. A quick search on the Haskell function search tool 'hoogle' finds the package Data.Foldable and tada.

We can now have a look at Either's Foldable instance, specifically, the foldr implementation (it's foldl is implemented using foldr).

foldr _ z (Left _) = z
foldr f z (Right y) = f y z

We're passing in a Left in this case, so we can just look at that first line which takes 'something', z and a Left and returns z. It clearly is ignoring the value inside the Left!

Looking at the second line, as can see that it is the Right side of the either that the foldr is running the function on.

We can see a similar thing looking at the types.

In fact, if we think a bit more about the type Either a b it makes sense that the f in our applyAll function isn't being matched by Either, it's being matched by Either a. This means that the 'contents' of our polymorphic type, f, is b, not a.

TLDR: I had the arguments to Either around the wrong way and Either err acts as if it were a list of 0 or 1 elements.

Here's the code from above

I've been using Linux for a little while and along the way have accumulated a fair bit of configuration (even though I try to remove the bits I don't need anymore).

I often find that these configs help me out (e.g. my Vim config) so, after the first few times I lost bits of it, I spent some time ensuring that I could keep it, even if I changed computers, had a hard drive fail or went mad and wrote a bunch of terrible configuration.

What amazing tool could solve my configuration backup problem?

Well, of course, its Git.

I keep any config and useful bash scripts that I need in a git repo. This includes:

So, lets step through what I needed to do this.

First, (assuming you are a Linux, or possibly Mac/BSD user) I'll assume you are familiar with a terminal (e.g. bash).

cd ~/.config

We're now in one of the most common places to store user specific configuration. Lets setup a git repo. I recommend using Github or Bitbucket.

This should give you an identifier for your git repo, mine is git@github.com:Cypher1/Castle.git.

git init
git remote add origin git@github.com:user/repo.git

Now you can add any files that you already have in .config.

git add important_file_to_backup
git commit -m "Adding important file"

Nice enough, but we are missing our actual dotfiles (the ones stored in our home directory).

So, lets grab those, I'll use my zshrc file as an example but you should be able to substitute to make this work for any dotfile.

First we move the actual dot file into our repo and add it.

mv ~/.zshrc ~/.config/zshrc
cd ~/.config/
git add zshrc
git commit -m "Adding my zshrc"

Now we need a bit of a trick to make it look (to our programs) like the dotfiles are still where we left them.

Fortunately there's a great tool for this called 'soft (or symbolic) links'. They make use of the structure of modern file systems to make a 'linked' version of a file or directory.

The utility to make soft links is called ln or link (find out more with man ln).

ln -s ~/.config/zshrc ~/.zshrc

This creates a new soft link at ~/.zshrc and connects it to ~/.config/zshrc.

Now programs that open ~/.zshrc will actually be opening ~/.config/zshrc, so all your edits will be tracked in the git repo.

Always remember to upload your changes to your remote repo so that you have them backed up.

git push origin master

I recommend learning more about git so that you can manage your backups and your changes to them.

For me, it was worth creating an installer script that does all my soft linking, and software installation.

You can find it here.

Résumé - Jay Pratt

Jay Pratt

5 years at Google.

Internships at Facebook and Microsoft.

Undergrad at UNSW: Computer Science and AI/ML.

 

Rust, C++, TypeScript, JavaScript, Datalog, Python, Haskell, Kotlin, Java, Bash, PHP (Hack), WASM, Meson & Ninja, Vim, Zsh, Github, Linux.

 

I am passionate about improving the lives of the people around me and using technology to automate and accelerate tasks. I have a range of experience but my particular interest is using Static Analysis and AI techniques to build better systems.

Experience

Logo for Google
Software Engineer
Google

2018 – Present (5 years 2 months)

I've had some great opportunities in the last few years working at Google. My team uses a wide range of tools and techniques from formal methods to implementing databases for Android. I also spent some time with the Chrome Operating System team as part of their virtual machine efforts. We took Linux VMs on Chrome OS from a PoC to a successful launch.

 

Projects
Raksha: static analysis for policy enforcement.
  • Working with client teams on IR generation
  • Implementing new theories for data flow analysis (enforcing non-fingerprinting)
  • Building infrastructure for custom model checking solver
Arcs: a runtime for modular, provably private, AI powered software.
Chrome OS: Linux VMs
  • Chrome OS User Interface theme work, including refactoring and maintaining48K LoC of CSS and multiple build tools
  • Patching aChrome extension for rendering a Chrome specific image format used for toolbars
  • Implementation work on USB device pass through
Logo for Github
Open source contributions
Compilers & Tooling

Ongoing

Logo for Tako Tako: an experiment in software verification
  • Leverages type checking and proof for optimisation and correctness
  • Prototypes have included:
  • Currently building:
Steel: a tiny optimising interpreter
  • Applied concepts from Game Development (Entity Component Systems) to compilers
  • Found ~30% runtime savings in benchmarks when applying simple static optimisations over naiverewriting ofASTs
  • Presented findings to Google Research Australia (talk available)
Ibis: a type system for privacy enforcement
  • Uses data flow analysis to enforce requirements avoiding leakage of PII (user data)
  • Used a type system with awareness of structure, sub-typing, and data flow tagging / 'taint'
  • 100% Rust, compiled to WASM for in-browser type & policy checking
Logo for Facebook
Software Engineer Intern
Facebook

Dec 2016 – Feb 2017 (3 months)

I really enjoyed working on automatic spam detection with the anti-spam team at Facebook. I learnt a lot about processing 'Big Data', scalable machine learning techniques and spam. I'd love to recommend interning with Facebook.

Logo for Microsoft
Software Engineer Intern
Microsoft

Dec 2015 – Feb 2016 (3 months)

Working on the Edge Extensions team was a great experience. The team worked on making Browser Extensions available in Edge so that users could use AdBlock, LastPass, and the Reddit Enhancement Suite in Edge. I worked with several developers to design and implement new power saving 'user presence' APIs which are now part of Edge.

Logo for UNSW
Computer Science Tutor
UNSW

2015 - 2018 (3 years)

I tutored courses in Data Structures, Algorithms, Programming and Debugging Techniques and later tutored the Advanced C++ course.

Logo for Rulingia.com
Front End Developer
Rulingia.com

Jul 2015 – Aug 2015 (2 months)

Developed a Web Interface for Customer Resource Management using AngularJS, Bootstrap, Sass and other tools as part of a small developer team of three.

Logo for the Decision Systems Laboratory (DSL) at UOW
Junior Researcher
UOW (Decision Systems Laboratory)

Nov 2013 – Mar 2014 (5 months)

I developed a simple tool for surveying medical professionals and the public and built a better understanding of Oncology using techniques in Statistical Ontology Verification.

Education

Logo for UNSW

BSci (Computer Science & AI)

UNSW
2014 – 2017

A Computer Science Degree from the University of New South Wales teaches students to solve problems especially by applying Computer Technology. Important skills that are core to Computer Science are teamwork, time management, problem solving and creative thinking. Computer Science is a wonderful set of ideas and approaches to problem solving and also a lot of fun. I thoroughly enjoyed my degree.

Interests

Contact

Feel free to write me an email here if you need a hand, have an idea you want to discuss or find a post I can improve on.

 

Resume for download (alternative: extended resume)