Last active
May 26, 2024 18:47
-
-
Save jimmydivvy/6e42ed2e43014ef55382 to your computer and use it in GitHub Desktop.
Simple IO Monad example in Javascript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class IO { | |
// We construct the IO type with a thunk/callback that returns the value when called | |
constructor( fn ){ | |
this.fn = fn; | |
} | |
// IO doesn't do anything until we explicitly call it. | |
run(){ | |
return this.fn(); | |
} | |
// Create a new IO value containing a thunk that calls the | |
// previous one and runs a translation on it | |
/// map :: IO a -> (a -> b) -> IO b | |
map(fn){ | |
return new IO(() => fn(this.run())) | |
} | |
// Create a new IO value with a monadic bind. Similar to `map`, but | |
// the underlying function itself returns an IO that must be unwrapped as well.s | |
/// bind :: IO a -> (a -> IO b) -> IO b | |
bind(fn){ | |
return new IO(() => fn(this.run()).run()) | |
} | |
} | |
// Log a value to the console using the IO monad. | |
// Rather than performing the action directly, it returns | |
// an IO value containing a thunk that will log to the console | |
// when called. | |
function ioLog( message ){ | |
return new IO( () => console.log(message)); | |
} | |
// "Pure" takes a primitive value and lifts it into the IO monad | |
function ioPure(value){ | |
return new IO( () => value ); | |
} | |
// Ask a question and then return the response. | |
function ioPrompt(question){ | |
return new IO( () => prompt(question)) | |
} | |
// This example uses 'pure' to provide a starting value, but you can replace with 'ioPrompt' | |
// to request a value from the user. | |
ioPure(5) // Start with the number 5 | |
.map( x => x * 2 ) // Double it | |
.map( x => x + 1 ) // Add one. (We not have `11`) | |
.bind( x => ioPure(100).map( y => // bind against another ioPure to simulate requesting data from somewhere. | |
x + y // Add the two values together to get 111 | |
)) | |
.bind( x => ioLog( x)) // Now we log the result to the console. | |
.run() // Run it. Nothing has happened until this, we just have a | |
// Chain of thunks/callbacks waiting to fire. | |
// Calling `run()` sets the whole thing into motion. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment