Skip to content

Instantly share code, notes, and snippets.

@micmarsh
Last active August 29, 2015 14:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save micmarsh/e9dcccf81ffdede88aff to your computer and use it in GitHub Desktop.
Save micmarsh/e9dcccf81ffdede88aff to your computer and use it in GitHub Desktop.
Haskell Do Notation for JavaScript Promises
COMPILED_COFFEE = ' < -'
PLAIN_JS = '<-'
thenify = (lines) ->
[line, rest...] = lines
if rest.length is 0
line
else if line.search(PLAIN_JS) > 0 or line.search(COMPILED_COFFEE) > 0
[value, promise] = line.split if line.search(PLAIN_JS) > 0 then PLAIN_JS else COMPILED_COFFEE
noSemiColon = promise.slice(0, -1)
"return #{noSemiColon}.then(function(#{value}){"+
thenify(rest) +
"});"
else
line + '\n' + thenify rest
doPromise = (fn) ->
lines = fn.toString().split '\n'
withArgs = lines[0]
body = lines.slice(1, -1).map (x) -> x.trim()
newFn = thenify(body)
with: (args...)->
eval("(#{withArgs}#{newFn}})")(args...)
# EXAMPLE
# doPromise (get, savetoDatabase)->
# data <- get 'some stuff'
# ids <- saveToDatabase data
# {data, ids}
# .with get, savetoDatabase
#
# compiles to:
#
# doPromise(function(get, savetoDatabase) {
# data < -get('some stuff');
# ids < -saveToDatabase(data);
# return {
# data: data,
# ids: ids
# };
# })["with"](get, savetoDatabase);
#
# which gets transformed into this:
#
# function (get, saveToDatabase) {
# return get('some stuff').then(function (data) {
# return saveToDatabase(data).then(function (ids) {
# return {
# data: data,
# ids: ids
# };
# });
# })["with"](get, savetoDatabase);
#
# yay monads!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment