Skip to content

Instantly share code, notes, and snippets.

View YBogomolov's full-sized avatar

Yuriy Bogomolov YBogomolov

View GitHub Profile
@YBogomolov
YBogomolov / session.ts
Last active January 13, 2025 09:30
Session types for TypeScript
// Inspired by https://github.com/Munksgaard/session-types
interface Chan<Env, Protocol> {
env_and_protocol: [Env, Protocol];
}
class Eps implements HasDual {
readonly tag: 'Eps' = 'Eps';
readonly dual!: Eps;
}
@YBogomolov
YBogomolov / never-intersect.ts
Created May 15, 2019 12:17
Type-level laws: "function arguments should never intersect"
export type If<T, U, True, False> = [T] extends [U] ? True : False;
export type IfDef<T, Yep, Nope> = If<T, never, Nope, Yep>;
export type Intersect<A extends {}, B extends {}> =
Pick<A, Exclude<keyof A, Exclude<keyof A, keyof B>>> extends { [x: string]: never } ?
never :
Pick<A, Exclude<keyof A, Exclude<keyof A, keyof B>>>;
const f = <
A extends {},
B extends {},
@YBogomolov
YBogomolov / syntax.test.ts
Last active January 13, 2025 09:24
TypeScript implementation of Haskell's do-notation
import { identity, Identity } from 'fp-ts/lib/Identity';
import { io, IO } from 'fp-ts/lib/IO';
import { doM } from './syntax';
describe('Monad do-syntax', () => {
beforeAll(() => {
jest.spyOn(Identity.prototype, 'chain');
jest.spyOn(IO.prototype, 'chain');
});
@YBogomolov
YBogomolov / tf.sc
Created November 3, 2018 18:39
Tagless Final example in Scala + Cats
import scala.language.higherKinds
import cats._
import cats.implicits._
final case class User(id: Integer, name: String, age: Integer, isAdmin: Boolean)
val fakeUsers: List[User] = List(
User(1, "John Connor", 32, false),
User(2, "John Smith", 18, false),
User(3, "Mark Brian", 28, false)
@YBogomolov
YBogomolov / tf.ts
Last active January 13, 2025 09:23
Tagless Final example with fp-ts
import { HKT, Type, URIS } from 'fp-ts/lib/HKT';
import { identity, Identity, URI } from 'fp-ts/lib/Identity';
import { Monad, Monad1 } from 'fp-ts/lib/Monad';
// Task: get all users named 'John' and make them admins
interface User {
id: number;
name: string;
age: number;
@YBogomolov
YBogomolov / free.ts
Created November 3, 2018 16:41
Free monads example with fp-ts
import { foldFree, liftF } from 'fp-ts/lib/Free';
import { identity, Identity } from 'fp-ts/lib/Identity';
// Task: get all users named 'John' and make them admins
interface User {
id: number;
name: string;
age: number;
isAdmin: boolean;
@YBogomolov
YBogomolov / 00-README.md
Created March 23, 2021 19:53
Статья про Task, TaskEither, ReaderTaskEither

Примеры кода для статьи на Хабре о функциональной замене промисам

Статья: https://habr.com/ru/post/548622

import { either } from 'fp-ts';
import { pipe } from 'fp-ts/function';
import Either = either.Either;
declare global {
interface ErrorConstructor<T extends string = string> extends Error<T> {}
interface Error<T extends string = string> {
readonly tag: T;
new<T extends string>(message?: string): Error<T>;
@YBogomolov
YBogomolov / inflate.ts
Last active July 11, 2023 09:51
Inflating objects
type Split<S extends string, D extends string> = S extends `${infer T}${D}${infer U}` ? [T, ...Split<U, D>] : [S];
type Join<T extends string[], D extends string> = T extends []
? ''
: T extends [infer F extends string, ...infer R extends string[]]
? `${F}${D}${Join<R, D>}`
: never;
type Inflate<T> = Compact<UnionToIntersection<{ [K in keyof T]: InflateInner<T[K], K & string>; }[keyof T]>>;
@YBogomolov
YBogomolov / uuid.ts
Last active June 21, 2023 14:15
Type-level UUID
type VersionChar =
| '1' | '2' | '3' | '4' | '5';
type Char =
| '0' | '1' | '2' | '3'
| '4' | '5' | '6' | '7'
| '8' | '9' | 'a' | 'b'
| 'c' | 'd' | 'e' | 'f';
type Prev<X extends number> =