Skip to content

Instantly share code, notes, and snippets.

@davidchase
Last active March 2, 2020 13:08
Show Gist options
  • Save davidchase/2f99911108a80ccf8ada988d8e82fcbf to your computer and use it in GitHub Desktop.
Save davidchase/2f99911108a80ccf8ada988d8e82fcbf to your computer and use it in GitHub Desktop.
https://flems.io/#0=N4IgZglgNgpgziAXAbVAOwIYFsZJAOgAsAXLKEAGhAGMB7NYmBvAHhLID4AdNNmDACbc0AAhEs41AE4QADsRFwp1ALxcQJYrLiIA9LoCuaWQGsA5vjpZDaCPQC0xAJ6yYAAQAM+ACz4AjLoCEHDENnZoji4w+ABWcOocLLqSMvLCYkmE-EI8GQBGtAJO6eK6BUXCmaRQHJQgcDCw1MThCIggAEyIAGwAHCAAvhTo2LjtUBB5sQhUdAxMxHgQWLK0UgrAIlJMAjBSIgMiYFK0WCIA5JraejamFla67Lqy2xjNycQYaAIYUPTRWEKBlg03OPB4MAAHqt1kcjM1wkcTlgAKIANwWAApnK4KCJGjAcAwAJQiYC5LYwYgGKSiMDwlr0TFoKHEUnk0RifGwInEfCCATohYAGWCjBZUmxUTxLMhbIpAx4irQEOhawU9LQCPoIiwGFkmLAeKU1HZFO21NpcK1jLQzNZZs5YhNmLRvxEKg4IllxENrt+xMDCqV4NlMI1DMRnwNkLxYEdYjAmMhxPNVJpokhIZVYfV1u1ohwUjMMGTcATlMtdMjTJ9FbEkLg+G2AgM1FL0ZlDuDaGVqvD+dtRyp1EIQoYmJpUArFozg-C9rl9eHxFHk6k04pXJE+GIWTt2zgsg9XsPsmmTKDTq5u-3i-l17Elgwq8I99TnOVfdzsM1BaOtBQAIBpgGgeIQLYLS-MaygzumVp-kO75kluIiwAobzUB6IgQRAUFQKhPqYphH7bi6iELmiy5iJh2GgcR1DUHiVGoWIREkahAykQc2b9nmFE6ts3x7AAIgA8gAspiJrMRAMAAO54o0WBwVW861g6KHXuRNZ2j8nzUd6rKYkJuySmicnyZi+kYMSSlQCp3FiFxPbflCA5zCEOECNhkIniIWY5u5eaeRhUDyRgThwNhGD+Xk-kYKGwW-rpWxGNJsFac6yiYhAAgfm5aopTaiIhBg6wAOp4W+saKJlHJiLOCG6chDVckRKaoS6dauUlRURiVOrSPwjDjsQACCPzyHsmIVqFAXRSoIjIAAummanIH5noLfgYBrCibxvmA-lJimdlHP5jb4LIBhwEdxJrb2fUefQXmyC+hDYcRUhSHitB5DEpLbeVUjNjArbtpiDFMQFQNerRABkCMiJhm0rX9APEnUDRNLabQgAA7AAzIgBPdIMwwgJgOB4NMdRzOKiztMsA6bOwUAHEipwXFcOj6EYdyWKcjykM8rzvGV3y-P8+CAq2IJxGCtgrHmbXDS+MBjZN+qML95pGBQFJFiWhucqZomSabiaAcBVu6vqdu-BFUV2+9e5KlzZznPgugTHkSs8OhIgAJIidhHg8PNyCEF8AiwGJaAAMITNQJh4tQKcmGNcArdh6ujRiDDa9NkoflHMffPHScVybOHGAYxDZ7nS355rhcTVNuuzZHr0KNHsewCJ-x4gI-xN3nrwFwsxddx+PD6CIABqlk8AJojLwpmKbDZMqjAcqlzuzAAGqEsEEaIlNuoohIgrHiLIl-buIEE3Qo9CJzXMAqAAJMAFdxzABOH8vglkOG6KABgv6-2pjAQ4uhH4ZGeAg8QeQG7EB1O-TOP8-4D0AUnTOAwOCTR8hJNYMAkioOIOgtAyCWDAmQWIX+NlZb6kxHfbcuVGBYHAnDdhT9j58KfuICYgihEiEwRAVO2DZr+X-oPf4nDCTEmVGI1RIgTAwCcNgiAKi1FCJCE4WA2C2p6KEYwOUIkYB0CkC+cIiAcJcPwKPFkIgAD8FwJgskcIQE4BgzCEHOCIex5xzh21MU-agNI4BrGCasCCutQmiNUeY4gAAVGxaA4B7SkFgYJ1B9R4V+BAAAXjAJW4TtwDF0eEhhajf54UJLuPCsBqmmKSBMWp24T6Pi5Mou+SR6Gn0CBAC+FJunKgXgAVTdjAVeqUDCyH0qWMqjA8TvUMbQQQ2FNhvFtMEgA+oEriWVKxzhMSuUc9iZHbS3jufA+AVkwBHi+DA9jHlOJeULLUL5MTrL+IIfA4DIGki4mEkOAA5AACpM1JVy4YiFufch5nxVnelGPYv5myBCAt+JA-eYLE7CmDonAA0nC-yW875IseWCti6KLiJJ6TZN5KLojMLmPk30mwWjEFgCyjW+AYHgQEPYgA1KK0OI9-j2LAL8Bo+9OJ2VQuJcFKJyU3POU+e5NK77MsUKyj5nwWEGh8p6Ph2K8oehUEtTFAKgXREte4zYSKBBSpZPYgAhNi5xMBOb2IEHfJy+LUL7PVV6R5CpkC2uxbs8IK1u5PRzPNDAcBonUEhR9GKcUKXOvuRgZiuKYAYo+sRHFECnkiDyCCsuvcUaptoFhJasVtrxQ1Xc-kBby32Pii5NAC8JIYAgjwKQ6U0zCSkOJKSqE9pAQNHfBZSzaUnKEXq1AIgeV8ouMccGoSRA+plXKiteV7GhwOOjPhMDgnlKfkMO+xtSzID4XqA0Ka023NjfQYJKqURHPOj67OSqeliGfcRcKkU4DvoLMEwlxKSW-vTpnADS7gOsNEa+htGa9yQb2RcYOUKYW7vtfY5A5xPjFipLu849rzi51BaIl+Dds58KDWIFaQbAPbg3opVCo9Im8nwOUJwFIPwfnpqcWQ0A9h4DyBgPIjRsYEgLPjAmABORAfgCaDBWgMIAA
https://flems.io/#0=N4IgtglgJlA2CmIBcB2AzAOjWgNCAZhAgM7IDaoAdgIZiJIgYAWALmLCHgMYD2lL8fshAAeAEY8oATwB8AHUoACReICuLFn3lLligMKwIXANaKAsvAXKRAejHrNlbbYnSZnEMXgIuLCH1IGACYkAEYgkABfHCpaekYAK1JuPgEhBggwAAceACcWRWBFVnZFSMV8XJ4wRQByVhYs4iQbG1VKLOMAcwxeMBsSmyzc+GpfG2IWakooalg+eAwwSVUEDCTahQV8dt9-JXx4Fi4mAFEAN0EWAApVXNgASkKrRRGWO4Pdvz4Ko5OIShda6UeAADxYT2AL2Uh2OTFu9we0N0GBYTEE1xGxCyigAvDJXvBsetiHxrg8kTpdIpUejKMCwRDkcpetQ4QzwZTlJEFDzKApeJRJoowNQsgBBPY-XGKa4sKRZeA4RTEXJcJ74546N4fCpffYisVZAFAkGcrXU1Vca7nOZ4glQqm6M03eWK5W2x7IyJcsq8raUQXC4gIeA4mVgYj2xQggDuigAClVIF5MUSeLBLtHHcovCwACqZeA8dRp0mZpUi4iUn0BnaB75KKDeahSa6R5VWyEvHW5T4N-YciEW3Qh+Bh9vV2kY8nZ5kqtVD33c318vkCgIFAByAHkt6c8YoAMpSMASWDXWpbha1SkboUFBPUCC5Q-XajKsQagnXHOKD8vGIOAvPgkxILOmoAToxAzEgsrfooQEvKKWRwfg0ZPi+77Kvg1xfg8wE6GImRinB1z4MqXQIZhuTke+BGKEC+G8ne-KUPWUpKKoWSzAI1yTGylZkGMjbKlkrbzNQUAALrdtqRy6n+yj5gAkmYpxkdRz60cAGB6QJAjKn4dBweJUiSVA0SKLu+4EciegADIqXoADSmkYdp1zzkUekYAZlbQHB-kYNAigANSKKEZSEdSygoZKjaXgAYqc+Z6AAErUOF-Gclz8JeDRNC0NgjAAjliIWUDYYoQG0Xi5MQAD8zawK2uJoLey6KHZToACKnA54oAJopWl6XuZqNG-jS+lTIZii8dQQVzYsi29HwXBstcZkWRgi1PFZNmnD11KjRlE0ElN3kzX5K3Koty2CXtbLUOtgZbTtPBSc9UwHTFsXxZxXlOtStT9YNI2pRlWXzsoLWttcACsAAMqPZXCFxXAVGhFa0ZUVQC1XGm0lDGJQPCxlVQSdfOXWrsJnHSeS-psRxjYVMmmP5W6lbePAdD8HJyi9v2QMukLuh8wLLAYFJUBcywDkQJMgjwLRPPKuLLxrgG2z6j8+AZlAWTkZQyoAhAfhzMq8B5Sw1YjiLeoDmS4sjsoCAFGMXCHlNFtW7AypHV1bMGiMXB3KmXbu6Oi6h2SvkukeK0S7F-5cD7Mr4PS3sYKBNwMUnKewzGjLvhneeTOSXXUhA6Hl1wfkzLOACEuIysHMdp+HkfwA3TdQNXJd8mntZOiPug9w1fe21c1bayz97CtAVyW1Ih6gtGoIBkGXuwLGrZRjK1DRmI0bUHW+tKLk7T8WqEtWtcK-8GvNaXy7SibbAsAAOqW-CoIcIS1wqCX0Ttt6UHXOxK+Io1ZdD7qCB2f4nbx3pG7JSihEEYBGFAVQXA+5f1-v-TWjJVyL1ZjAqYJsKILnVI7BSfZnZi1ITHR+s9+BzhBhUa47CmRcJdDwu2XUx7cnIagxQs9chtg7BUSgEsUFXyXKwo4Kl+Bq09NcCCBIBHZ2rsqSMZDIEBhvvSF4VDgbUiDBmRY8wejEWblYtYtjlS1CoYqKAigSwsCQLef6MIjYm3nNxXiSprqBUUMje6L04JkGkkZIscFai1GivOQGiVaiOWci5LKHNqgK0vFwQwJgclQB4BHaWGBXBSApMiX0lJKS70NBKTiR9MFHwJPALexAd6bkUOcCA8B4wyhKLAAABmoDQPw+AGCMMYXEAASYAaT9jEGuGQDJTlXI5NqGdTKslIgyBmSYcw8AXAOC0KMnpD5FDBMEmYSQ3g3z+WVAzUSihPpSVkpw4WDClAYI2Vk2oF1ZS6VmoJKJUxHoCB+q9QUm0bgfKgA8ERfojFsUabvG+vhTj4E3jKHh+BDi+GIC8kS+wxISS+jJBCyDfkxx2VDTKwLYQnHybUO4sBbwLzRQoDwfRjQIFyMIMQ1AxDeA8F4HwjZAggGRkgZGABaUIAAWRG8qogxBADQOgwhejEGSCAQUaQWDCCiNJSIQA
import { html } from 'https://unpkg.com/htm/preact/standalone.module.js'
function fetchEvent(url) {
return function fetching(next) {
fetch(url)
.then(resp => resp.json())
.then(next)
.catch(next)
}
}
const mapAction = (type, src) => {
return function mapping(next) {
src(val => {
next(type, val)
})
}
}
const sleep = ms => new Promise(resolve => {
setTimeout(resolve, ms)
})
function delay(ms, src) {
return function(next) {
sleep(ms).then(() => {
src(next)
})
}
}
const NONE = Symbol('None')
const Pair = (a, b) => ({
a,
b,
fst:() => a,
snd: () => b,
map: f => Pair(a, f(b)),
bimap: (f, g) => Pair(f(a), g(b))
})
function update(state, [action, payload]) {
return {
TIME: () => Pair({...state, time: payload}, NONE),
CLICK: () => Pair(
{ ...state, id: state.id + 1 },
mapAction('FETCH', fetchEvent('https://reqres.in/api/users?delay=3'))
),
DELAYFETCH: () => Pair({ ...state, data: state.data.concat(payload.data) }, NONE),
FETCH: () => Pair(
{ ...state, data: state.data.concat(payload.data) },
mapAction(
'DELAYFETCH',
delay(5000, fetchEvent('https://reqres.in/api/unknown/2'))
)
)
}[action]()
}
function fromEvent(type, element) {
return function(next) {
element.addEventListener(type, next)
}
}
function foldp(fn, initial, events) {
return function(next) {
let acc = Pair(initial, NONE)
function recurse(src) {
src(function(...nextState) {
acc = fn(acc.fst(), nextState)
next(acc.fst())
if (acc.snd() !== NONE) {
recurse(acc.snd())
}
})
}
recurse(events)
}
}
const identity = x => x
const always = a => b => a
function run(src) {
src(identity)
}
function callWith(x, f) {
f(x)
return x
}
function merge(xs) {
return function(next) {
xs.reduce(callWith, next)
}
}
function tap(f, src) {
return function(next) {
src(event => {
f(event)
next(event)
})
}
}
function every(ms, fn) {
return function(next) {
setInterval(() => next(fn()), ms)
}
}
run(
tap(
console.log.bind(console.log, 'tapped out:'),
foldp(
update,
{ id: 0, data: [], time: '' },
mapAction('CLICK', fromEvent('click', document.body))
)
)
)
const mapActions = xs => e => xs
const view = html`<button onClick=${mapActions(['CLICK', 'FETCH'])}>Click Me</button>`
const updateModel = (state, [action, payload]) => {
return {
'CLICK': () => ({...state, data: state.data.concat(payload)})
}
}
const constructEfx = (effects, [action, payload]) => {
return {
'FETCH': () => fetchEvent('url')
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment