import { Spec, createEffect, Effectful } from 'hyogwa';
import { unsafeRunSync } from 'hyogwa/runners';
// Definition of IO Effect
interface IO extends Spec<'IO'> {
read(): string
write(text: string): void
}
const IO = createEffect<IO>('IO')
// Definition of main function with IO effect
function* main(): Effectful<IO, void> {
const name = yield* IO.read()
yield* IO.write(`Welcome to hyogwa, ${name}!`)
}
// Running main function
unsafeRunSync(main(), {
IO: {
read({ resume }) {
resume(prompt() || '')
},
write(text, { resume }) {
alert(text)
resume()
}
}
})
No more suspicious wrapper functions, No more mess with pipelines, No more scary types. Just plain typescript functions, and plain typescript functions only.
⚠️ CAUTION: This project is work-in-progress. Use at your own risk!
For some codes, we may consider only its result.
When we read an arithmetic expression or a boolean expression we just evaluate it, remember the result and move to next code.
For the other codes, however, we should consider not only its result but also effects it may affect.
Calling the console.log
function results in not only undefined
value but also log in the console and
evaluating assignment expression like a = 1
results in not only some value but also changes of the value of variable
or the scope. If we regard shape of codes and evaluation result value of codes as extensional information(or in simple word, 'interface') of code,
we can think the other information -- like "this code will make a log in the console" or "this code will change the value of variable" -- that rises from the code while evaluation
intensional information(or in our well known term, 'side effects'). Those intensional information are matters as much as extensional information are since
no single one can be easily ignored and we programmers should mind all of them just like they treat extensional information.
Our type system, however, only values extensional information and hardly check possible problems that may happen because of intensional information.
All the burdens of inspecting, remembering, reasoning intensional information of code are passed to programmers.
That's why we be always bothered by errors like 'undefined is not an object' and 'unhandled promise rejection'.
Effect systems solve this giant problem. They encode intensional information of code as types so that type system can recognize and reason on intensional information.
By sharing burdens of treating intensional information (once we solely handled) with type system and its automated type checking algorithm
we can achieve better programming experience, and better programming experience leads to many advantages like productivity.
So far was the reason you should bring effect systems in your codebases. Now I'm going to explain why your choice have to be hyogwa. Before start, here's the summary:
- 🌿 Natural interface: No more suspicious wrapper functions, or cumbersome utilities; Write codes as you write plain typescript code.
- 🏃 Write once, runs everywhere: You can perfectly decouple business logics from platform specific logics.
- 🧑💻 Advanced development experience: Built-in coding assistant ready for you; it works without extra configuration.
- ⏳ Minimal interface: You can start writing code right after only learning three functions and two types.
- 🗽 Platform independence: You can use hyogwa in everywhere; hyogwa has zero dependency.
WIP