Closed
Description
📖 Documentation
Thank you for your contributions.
I suggest you put some syntactic sugar for monad chains in the tutorial examples. While you prepared the good tutorial example, it was painful for me to read and understand what it is doing. (I'm still a beginner) I managed to write a runnable code using the Do-notation, provided in fp-ts-contrib
. I think it needs kind of for-comprehension in scala or do-notation in haskell for better readability and usability. For now, Do
in fp-ts-contrib
may be a good choice.
tutorials/fp-ts-to-the-max-I.ts
import * as T from 'fp-ts/lib/Task'
import { Task } from 'fp-ts/lib/Task'
import * as C from 'fp-ts/lib/Console'
import { createInterface } from 'readline'
import * as O from 'fp-ts/lib/Option'
import { Option } from 'fp-ts/lib/Option'
import * as R from 'fp-ts/lib/Random'
import { Do } from 'fp-ts-contrib/lib/Do'
// Helpers
const getStrLn: Task<string> = () =>
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> => T.fromIO(C.log(message))
const random = T.fromIO(R.randomInt(1, 5))
const parse = (s: string): Option<number> => {
const i = +s
return isNaN(i) || i % 1 !== 0 ? O.none : O.some(i)
}
// Game
const checkContinue = (name: string): Task<boolean> =>
Do(T.task)
.do(putStrLn(`Do you want to continue, ${name}?`))
.bind('answer', getStrLn)
.bindL('result', ({ answer }) => {
switch (answer.toLowerCase()) {
case 'y':
return T.of(true)
case 'n':
return T.of(false)
default:
return checkContinue(name)
}
})
.return(({ result }) => result)
const parseFailureMessage = putStrLn('You did not enter an integer!')
const gameLoop = (name: string): Task<void> =>
Do(T.task)
.bind('secret', random)
.do(putStrLn(`Dear ${name}, please guess a number from 1 to 5`))
.bind('guess', getStrLn)
.doL(({ secret, guess }) =>
O.fold(
() => parseFailureMessage,
(x: number) =>
x === secret
? putStrLn(`You guessed right, ${name}!`)
: putStrLn(`You guessed wrong, ${name}! The number was: ${secret}`),
)(parse(guess)),
)
.bind('shouldContinue', checkContinue(name))
.doL(({ shouldContinue }) =>
shouldContinue ? gameLoop(name) : T.of(undefined),
)
.return(_ => undefined)
const nameMessage = putStrLn('What is your name?')
const askName = Do(T.task)
.do(nameMessage)
.bind('name', getStrLn)
.return(({ name }) => name)
const main: Task<void> = Do(T.task)
.bind('name', askName)
.doL(({ name }) => putStrLn(`Hello, ${name} welcome to the game!`))
.doL(({ name }) => gameLoop(name))
.return(_ => undefined)
main()
Metadata
Metadata
Assignees
Labels
No labels
Activity