In notebook:
FrontEndMasters Hardcore Functional
Created at:
Functional Programming JavaScript Fundamentals

IO is functor. But instead of a value, list, object, you put a function inside it.

  • A lazy computation "builder"
  • Typically used to contain side effects
  • You must runIO to perform the operation
  • Map appends the function to a list of things to run with the effectful value

Every time you map over an IO, it will compose inside it. The others we've seen just take values, but this one takes functions.

So your app just builds up a computation with IO, then you run it. This is lazy computation nothing runs at first.

  var email_io = IO(function () { return $('#email').val()})
var msg_io = map(concat('welcome'), email_io)

// → 'welcome'

email_io gets the value of an email field. Then msg_io maps over this value. So we're mapping over a function!

You think you're mapping over the eventual value, but in fact mapping over the function.

It's a lazy computaion because you runIO(msg_io) at the end.

  var getBgColor = compose(get('background-color'), JSON.parse)
var bgPref = compose(map(getBgColor), Store.get('preferences'))

var app = bgPref()
// => IO()

// now, you run your app
// this is how you kick it off
// #efefef

above, Store.get('preferences') returns an IO (local data storage, etc.)
so when you declare app, you don't yet run your app, you get an IO. Note: We have to runIO(app) in the end to kick it off.

IO is a bit like a Promise. You can also embed one into another.

One big difference is that a Promise will run at declaration, while IO will lazy run.

About question asked if runIO will automtacilly kick off other IOs? No it will not. Monads will solve that. Monads allow you to join together Maybes, IOs, etc.

One more thing

  var email_io = IO(function () { return $('#email').val()})

var getValue = function (sel) { return $(sel).val() }.toIO()

getValue will lazy run. Notice the .toIO() at the end. We can pass arguments to the function inside the IO. email_io will run immediately, getValue will lazy-run. Also, we can also pass arguments (sel) to getValue. So this, second pattern is more useful and this is the pattern he will be using.