For example, say this is my function:
let fib = n => {
  switch (n) {
    case 0: return 0
    case 1: return 1
    default: return fib(n - 1) + fib(n - 2)
  }
}
I can then implement a basic memoize function...
let memoize = fn => {
  let cache = new Map   // mutates!
  return _ => {
    if (!cache.has(_)) {
      cache.set(_, fn(_))
    }
    return cache.get(_)
  }
}
... And use it to implement a memoized fib:
let fib2 = memoize(n => {
  switch (n) {
    case 0: return 0
    case 1: return 1
    default: return fib2(n - 1) + fib2(n - 2)
  }
})
However, that memoize function uses mutable state internally. I can reimplement memoize as a monad, so every time we call fib it returns a tuple of [value, fib] where fib now has something in cache, leaving the original fib unmodified.
The downside of the monad approach is it is not idiomatic JavaScript, and is hard to use without a static type system.
Is there some other way to implement a memoize function that avoids mutation, without resorting to monads?
 
    