Skip to content

Instantly share code, notes, and snippets.

@fvilante
Last active March 6, 2019 23:11
Show Gist options
  • Save fvilante/2f53b699794c1ac35e087872e0acac98 to your computer and use it in GitHub Desktop.
Save fvilante/2f53b699794c1ac35e087872e0acac98 to your computer and use it in GitHub Desktop.
maybe
namespace Maybe_ {
type n = Extract
type Undefined = typeof Undefined
const Undefined = Symbol.for("None") // undefined
interface Just<T> {
readonly type: "Just",
readonly val: T | Undefined
}
interface None<T> {
readonly type: "None",
readonly val: T | Undefined
}
export interface Maybe<T> {
readonly type: "Maybe"
readonly val: Just<T> | None<T>
}
export const Just = <T>(val: T ): Maybe<T> =>
({ type: "Maybe", val: { type: "Just", val } })
const None_ = <T>(val: T ): Maybe<T> =>
({ type: "Maybe", val: { type: "None", val } })
export const None = None_<Undefined>(Undefined)
namespace Test_of_Implicity_Inference{
// ********************************************************************************************
// TESTE DE INFERENCIA IMPLICITA DO MAYBE
// ********************************************************************************************
// -----------------------------------------------
// inferencia basica . . .
// -----------------------------------------------
// a00 é inferido como: Maybe<Number>, e assim por diante . . .
const a00 = Just(10)
// Maybe<Number>[]
const a01 = [Just(10), Just(20)]
// Maybe<undefined>[]
const a04 = [None, None]
// -----------------------------------------------
// none implicito / explicito . . .
// -----------------------------------------------
// Maybe<undefined>
const a03 = None;
// Maybe<number>
const a031 = None as unknown as Maybe<number>
// Maybe<number>
//const a032 = Maybe(None)
// -----------------------------------------------
// tipos cruzados . . .
// -----------------------------------------------
// Maybe<Number>[]
const a02 = [Just(10), None, None]
// Maybe<Number>[]
const a05 = [None, None, Just(10)]
// Maybe<string>
const a06 = [None, None, Just("Joaquim")]
// -----------------------------------------------
// tipos cruzados e mistos. . .
// -----------------------------------------------
// Maybe<Number> | Maybe<string>
const a07 = [ None, None, Just(10), Just("Joaquim")]
// -----------------------------------------------
// tipos definidos pelo usuario . . .
// -----------------------------------------------
interface User {
name: string
age: number
}
const user1: User = { name: "Nelson", age:12 }
const user2: User = { name: "Juca", age:15 }
// Maybe<User>
const a08 = [Just(user1), None, Just(user2)]
// Maybe<User> | Maybe<string>
const a09 = [Just(user1), None, Just(user2), Just("Noise")]
// -----------------------------------------------
// Discriminacao pelo construtor . . . (conforme Haskell)
// -----------------------------------------------
//Maybe<undefined>
const a10 = Just(undefined) // isJust(a10) === true
//Maybe<undefined>
const a11 = None // isJust(a11) === false
}
}
namespace PatternMatch {
import Just = Maybe_.Just
import None = Maybe_.None
import Maybe = Maybe_.Maybe
const a10 = [Just(10), Just(20), None]
type InferMaybeType<T> = T extends Maybe<infer U> ? U : never
type Maybe_<T> = Maybe<InferMaybeType<T>> // helper for brevity
type GetMaybeConstructors<T extends Maybe_<T>> = T['val']['type']
type CallBack<T, U> = (value: T) => U
type Match<T extends Maybe_<T>> = {
[Constructor in GetMaybeConstructors<T>]: CallBack< InferMaybeType<T>, any >
}
const match = <T extends Maybe_<T>>(maybe: T, match_: Match<T>) => {
const typeOfMaybeConstructor = maybe.val.type
const valueOfMaybe = maybe.val.val
return match_[typeOfMaybeConstructor](valueOfMaybe)
}
function plus_one(x: Maybe<number>): Maybe<number> {
return match(x, {
None: () => None,
Just: (i) => Just(i+1)
})
}
const five = Just(5)
const six = plus_one(five)
const none_ = plus_one(None)
}
namespace mapStream_ {
export interface EventGenerator {
onEvent: (h: EventHandler) => void
}
type Food = string
export type Event = Food
export type EventHandler = (f: Event) => void
const foodStream : EventGenerator =
{
onEvent: (handler: EventHandler) => {
setTimeout( () => handler("galinha") , 1000 )
setTimeout( () => handler("vaca") , 2000 )
setTimeout( () => handler("milho"), 3000 )
}
}
foodStream.onEvent( (food: Event):void => console.log(food) )
}
namespace BigProtocol{
import StreamEvents = mapStream_.EventGenerator
import Event = mapStream_.Event
import EventHandler = mapStream_.EventHandler
const serialStream: StreamEvents = {
onEvent: undefined
}
}
namespace FullExample_Of_UseState_Implementation {
namespace utils_ {
export type Tree<T> = Array<T>
export const mapTree = <T,U>(fn: (a:T) => U, tree: Tree<T>):Tree<U> => tree.map(fn)
export interface IdentifiedElement<T> {
id: number
element: T
}
const counter = {
id: 0,
next() { const y = this.id; this.id = this.id + 1; return y }
}
export const placeIdentifiers = <T>(tree: Tree<T>): Tree<IdentifiedElement<T>> => {
const id = counter
const identifyElement = (element:T):IdentifiedElement<T> => ({ id: id.next(), element })
return mapTree( identifyElement, tree)
}
}
namespace useState_ {
}
namespace dispatcher_ {
import Component = React_.Component
type Pointer = number;
type MemoryCell = unknown
type ComponentMemory = {
[key: Pointer]: MemoryCell
}
type Memory = {
[key: Pointer]: ComponentMemory
}
let memory: Memory = { }
let componentPointer: Pointer = undefined
let variablePointer: Pointer = undefined
type Setter<T> = (val: T) => void
type UseStateResult<T> = [T, Setter<T>]
export const useState = <T>(initialValue:T): UseStateResult<T> => {
const getValue = ():T => {
//initialize if necessary
if (memory[componentPointer][variablePointer] === undefined)
memory[componentPointer][variablePointer] = initialValue
const currentValue = memory[componentPointer][variablePointer]
return currentValue
}
const getSetter = (pointer1,pointer2):Setter<T> => (val:T) => { memory[pointer1][pointer2] = val }
variablePointer = variablePointer + 1
return [getValue(), getSetter(componentPointer,variablePointer)]
}
const run = component => component()
export const dispatchComponent = (id: number, component: Component): ReturnType<Component> => {
componentPointer = id
variablePointer = 0
return run(component)
}
}
namespace React_ {
import Tree = utils_.Tree
import mapTree = utils_.mapTree
import placeIdentifiers = utils_.placeIdentifiers
import componentDispatcher = dispatcher_.dispatchComponent
type Props = undefined
export type HtmlJsx = string | undefined
export type Component = (a: Props) => HtmlJsx
export type ComponentID = number
export const React = (root: Tree<Component>):Tree<HtmlJsx> =>
mapTree( ({id, element}) => componentDispatcher(id, element), placeIdentifiers(root) )
}
namespace Example {
import HtmlJsx = React_.HtmlJsx
import React = React_.React
import useState = dispatcher_.useState
// Some Componentes
const incrementer = (props):HtmlJsx => {
const [count, SetCount] = useState(0)
const [countBig, SetCountBig] = useState(100)
SetCount(count+1)
SetCountBig(countBig+50)
return `count: ${count+1} -- Big: ${countBig+50}`
}
const decrementer = (props):HtmlJsx => {
const [count, SetCount] = useState(0)
SetCount(count-1)
return `<div> <p> ${count-1} </p> </div>`
}
// mount react Root component
React([incrementer, decrementer])
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment