Skip to content

Instantly share code, notes, and snippets.

@gcanti
Created August 8, 2018 14:11
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save gcanti/8b4bddd6711c10ca3ce7073abd1949a3 to your computer and use it in GitHub Desktop.
Save gcanti/8b4bddd6711c10ca3ce7073abd1949a3 to your computer and use it in GitHub Desktop.
TypeScript port of the first half of John De Goes "FP to the max" (https://www.youtube.com/watch?v=sxudIMiOo68)
import { log } from 'fp-ts/lib/Console'
import { none, Option, some } from 'fp-ts/lib/Option'
import { randomInt } from 'fp-ts/lib/Random'
import { fromIO, Task, task } from 'fp-ts/lib/Task'
import { createInterface } from 'readline'
//
// helpers
//
const getStrLn: Task<string> = new Task(
() =>
new Promise(resolve => {
const rl = createInterface({
input: process.stdin,
output: process.stdout
})
rl.question('> ', answer => {
rl.close()
resolve(answer)
})
})
)
const putStrLn = (message: string): Task<void> => fromIO(log(message))
const random = fromIO(randomInt(1, 5))
const parse = (s: string): Option<number> => {
const i = +s
return isNaN(i) || i % 1 !== 0 ? none : some(i)
}
//
// game
//
const checkContinue = (name: string): Task<boolean> =>
putStrLn(`Do you want to continue, ${name}?`)
.chain(() => getStrLn)
.chain(answer => {
switch (answer.toLowerCase()) {
case 'y':
return task.of(true)
case 'n':
return task.of(false)
default:
return checkContinue(name)
}
})
const gameLoop = (name: string): Task<void> =>
random.chain(secret =>
putStrLn(`Dear ${name}, please guess a number from 1 to 5`)
.chain(() =>
getStrLn.chain(guess =>
parse(guess).fold(
putStrLn('You did not enter an integer!'),
x =>
x === secret
? putStrLn(`You guessed right, ${name}!`)
: putStrLn(`You guessed wrong, ${name}! The number was: ${secret}`)
)
)
)
.chain(() => checkContinue(name))
.chain(shouldContinue => (shouldContinue ? gameLoop(name) : task.of(undefined)))
)
const main: Task<void> = putStrLn('What is your name?')
.chain(() => getStrLn)
.chain(name => putStrLn(`Hello, ${name} welcome to the game!`).chain(() => gameLoop(name)))
main.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment