๐Ÿ“ฆ ubugeeei / monadic-vue

Hobby / Monadic Vue.js

โ˜… 0 stars โ‘‚ 0 forks ๐Ÿ‘ 0 watching
๐Ÿ“ฅ Clone https://github.com/ubugeeei/monadic-vue.git
HTTPS git clone https://github.com/ubugeeei/monadic-vue.git
SSH git clone git@github.com:ubugeeei/monadic-vue.git
CLI gh repo clone ubugeeei/monadic-vue
Loading files...
๐Ÿ“„ README.md

monadic-vue

This is a hobby project. Not intended for production use.

Vue Reactivity (Ref) as Monad, Comonad, and Bimonad.

Based on the observation that Vue's Ref satisfies both Monad laws and Comonad laws (under extensional equality).

API

All multi-argument functions are curried (data-first for TypeScript inference).

Functor

  • map(refA)((a) => b) โ€” Ref(A) โ†’ (A โ†’ B) โ†’ Ref(B)

Monad

  • pure(value) โ€” ฮท: A โ†’ Ref(A)
  • flat(refRefA) โ€” ฮผ: Ref(Ref(A)) โ†’ Ref(A)
  • flatMap(refA)((a) => refB) โ€” >>=: Ref(A) โ†’ (A โ†’ Ref(B)) โ†’ Ref(B)
  • wrap(innerRef) โ€” creates Ref(Ref(A)) without Vue auto-unwrapping

Comonad

  • extr(refA) โ€” ฮต: Ref(A) โ†’ A
  • extd(refA)((w) => b) โ€” Ref(A) โ†’ (Ref(A) โ†’ B) โ†’ Ref(B)
  • dup(refA) โ€” ฮด: Ref(A) โ†’ Ref(Ref(A))

Composition

  • comp(f)(g) โ€” Kleisli: (A โ†’ Ref(B)) โ†’ (B โ†’ Ref(C)) โ†’ (A โ†’ Ref(C))
  • pipe(refA, f, g, ...) โ€” do-notation-like chaining

Example

import { ref } from "vue";
import { flatMap, pure, extr, extd, map } from "monadic-vue";

const count = ref(3);
const items = ref([10, 20, 30, 40, 50]);

// Monadic flatMap (data-first โ€” types inferred)
const sliced = flatMap(count)((n) =>
  flatMap(items)((list) => ref(list.slice(0, n))),
);

// Comonadic extd
const doubled = extd(count)((w) => extr(w) * 2);

// Functor map
const label = map(count)((n) => `count: ${n}`);

// Bimonad compatibility: ฮต โˆ˜ ฮท = id
extr(pure(42)); // 42

License

MIT