Skip to content

Instantly share code, notes, and snippets.

View Schniz's full-sized avatar

Gal Schlezinger Schniz

View GitHub Profile
////////////////////////////////////////////////////////////// Array utilities
type Length<T extends any[]> = T["length"];
type Head<T extends any[]> = T[0];
type Tail<T extends any[]> = ((...xs: T) => any) extends ((_x: any, ...xs: infer R) => any) ? R : [];
type AllTrue<Ts extends any[]> = {
0: true,
1: false,
2: AllTrue<Tail<Ts>>
}[Length<Ts> extends 0 ? 0 : Head<Ts> extends false ? 1 : 2]
@Schniz
Schniz / rmt
Created August 27, 2019 08:49
Remind me to (using Apple reminders)
#!/bin/bash
echo '
activate application "Reminders"
tell application "System Events" to keystroke "n" using command down
tell application "System Events" to keystroke "'"$*"'"
tell application "System Events" to keystroke return
' | osascript -
@Schniz
Schniz / typesafe-commander.ts
Last active July 31, 2019 10:52
TypeSafe builder pattern for commander
import { Command } from 'commander';
export class Program<ArgumentTypes extends { [key: string]: any }> {
private readonly parseFn: (cmd: Command) => ArgumentTypes;
private readonly command: Command;
constructor(command: Command, parse: (cmd: Command) => ArgumentTypes) {
this.parseFn = parse;
this.command = command;
}
@Schniz
Schniz / event_emitter.ts
Created July 25, 2019 09:11
Typesafe event emitters
class EventEmitter<T extends object> {
private readonly listeners: {
[key in keyof T]?: ((value: T[key]) => void)[];
} = {};
emit<Event extends keyof T>(event: Event, value: T[Event]) {
const listeners = this.listeners[event];
if (listeners) {
listeners.forEach(listener => listener(value));
@Schniz
Schniz / TaskEither_record.ts
Last active August 8, 2019 06:25
A record combinator for fp-ts TaskEither
import * as te from 'fp-ts/lib/TaskEither';
import * as arr from 'fp-ts/lib/Array';
import { pipe } from 'fp-ts/lib/pipeable';
type TaskEither<A, B> = te.TaskEither<A, B>;
type TERight<T> = T extends TaskEither<any, infer R> ? R : never;
/**
* Transforms an object of `TaskEither`s into a TaskEither of the resolved objects.
function add2(a: number, b: number) {
return a + b;
}
function add4(a: number, b: number, c: number, d: number) {
return a + b + c + d;
}
function concat(a: string, b: string) {
return (a + b).length;
class Lens<RootObject extends object, ChangableObject> {
getter: (x: RootObject) => ChangableObject;
setter: (x: RootObject, newValue: ChangableObject) => RootObject;
static simple<RootObject extends object, T extends keyof RootObject>(
name: T
) {
return new Lens<RootObject, RootObject[T]>(
x => x[name],
(x, v) => ({ ...x, [name]: v })
@Schniz
Schniz / README.md
Last active September 18, 2018 23:51
add typed `init_with` to Crystal Crecto models

Usage

class User < Crecto::Model
  schema "users" do
    field :name, String
  end
end

user = User.init_with(name: "hello") # doesn't fail
@Schniz
Schniz / result_type.cr
Created September 18, 2018 18:02
Result type for Crystal
record Ok(O), result : O
record Err(E), error : E
## hopefully it could have been
# alias Result(O, E) = Ok(O) | Error(E)
## but it can't
def mytest(i)
if i < 0
Ok.new(i)
@Schniz
Schniz / Angle.re
Created June 23, 2018 12:44
Two-dimensional vector addition and degrees conversions
let pi = 4.0 *. atan(1.0);
type t =
| Radians(float)
| Degrees(float);
let toRadians = d =>
switch (d) {
| Radians(d) => Radians(d)
| Degrees(d) => Radians(d *. pi /. 180.)