Introduction of Algebraic Effects

EXAMPLE

AND

DEFINITION

©hijiangtao

Example - try/catch

function getName(user) {
  let name = user.name;
  if (name === null) {
    throw new Error('A girl has no name');
  }
  return name;
}

function makeFriends(user1, user2) {
  user1.friendNames.add(getName(user2));
  user2.friendNames.add(getName(user1));
}

const arya = { name: null };
const gendry = { name: 'Gendry' };
try {
  makeFriends(arya, gendry);
} catch (err) {
  console.log("Oops, that didn't work out: ", err);
}

©hijiangtao

- There's no way we can continue executing the original code

- We want something just like if/for for goto, async/await for callback hell

But

©hijiangtao

Hypothesis first

  1. try/handle try/catch

  2. perform throw

  3. +resume

©hijiangtao

function getName(user) {
  let name = user.name;
  if (name === null) {
    name = perform 'ask_name';
  }
  return name;
}

function makeFriends(user1, user2) {
  user1.friendNames.add(getName(user2));
  user2.friendNames.add(getName(user1));
}

const arya = { name: null };
const gendry = { name: 'Gendry' };
try {
  makeFriends(arya, gendry);
} handle (effect) {
  if (effect === 'ask_name') {
    resume with 'Arya Stark';
  }
}

©hijiangtao

function getName(user) {
  let name = user.name;
  if (name === null) {
    name = perform 'ask_name';
  }
  return name;
}
try {
  makeFriends(arya, gendry);
} handle (effect) {
  if (effect === 'ask_name') {
    resume with 'Arya Stark';
  }
}

1⃣️ Perform an effect

2⃣️ Jump to the handler

3⃣️ Resume with a value

4⃣️ End up back here with "name"

©hijiangtao

MORE

THAN
Try/Catch

©hijiangtao

❌ async/sync in the meantime

// If we want to make this async...
async getName(user) {
  // ...
}

// Then this has to be async too...
async function makeFriends(user1, user2) {
  user1.friendNames.add(await getName(user2));
  user2.friendNames.add(await getName(user1));
}

// And so on...

©hijiangtao

One-shot delimited continuation

try {
  makeFriends(arya, gendry);
} handle (effect) {
  if (effect === 'ask_name') {
    setTimeout(() => {
      resume with 'Arya Stark';
    }, 1000);
  }
}
try {
  makeFriends(arya, gendry);
} handle (effect) {
  if (effect === 'ask_name') {
    resume with 'Arya Stark';
  }
}

Mechanics of algebraic effects

When we throw an error, the JavaScript engine “unwinds the stack”, destroying local variables in the process. However, when we perform an effect, our hypothetical engine would create a callback with the rest of our function, and resume with calls it.

©hijiangtao

SEPARATE

WHAT

FROM HOW

©hijiangtao

STEP 1 / WHAT TO DO

function enumerateFiles(dir) {
  const contents = perform OpenDirectory(dir);
  perform Log('Enumerating files in ', dir);
  for (let file of contents.files) {
  	perform HandleFile(file);
  }
  perform Log('Enumerating subdirectories in ', dir);
  for (let directory of contents.dir) {
  	// We can use recursion 
  	// or call other functions with effects
  	enumerateFiles(directory);
  }
  perform Log('Done');
}

©hijiangtao

STEP 2 / HOW TO DO

let files = [];
try {
  enumerateFiles('C:\\');
} handle (effect) {
  if (effect instanceof Log) {
  	myLoggingLibrary.log(effect.message);
  	resume;
  } else if (effect instanceof OpenDirectory) {
  	myFileSystemImpl.openDir(effect.dirName, (contents) => {
      resume with contents;
  	});
  } else if (effect instanceof HandleFile) {
    files.push(effect.fileName);
    resume;
  }
}
// The `files` array now has all the files

©hijiangtao

WHAT'S

MORE

©hijiangtao

Should we add Algebraic Effects to JavaScript?

// ES2100
perform Timeout(1000);
perform Fetch('google.com');
perform ReadFile('file.txt');
perform Timeout(1000);
perform Fetch('google.com');
perform ReadFile('file.txt');

Is this relevant to React?

function LikeButton() {
  // How does useState know 
  // which component it's in?
  const [isLiked, setIsLiked] 
  	= useState(false);
}

©hijiangtao

TAKE

AWAY

©hijiangtao

©hijiangtao

     
https://overreacted.io/algebraic-effects-for-the-rest-of-us/
https://github.com/ocamllabs/ocaml-effects-tutorial
https://www.janestreet.com/tech-talks/effective-programming/
https://www.youtube.com/watch?v=hrBq8R_kxI0
https://en.wikibooks.org/wiki/Common_Lisp/Advanced_topics/Condition_System
https://jlongster.com/Whats-in-a-Continuation

Q&A

©hijiangtao