Skip to content

Commit 8040f29

Browse files
committed
update alacarte example
1 parent bf2db7c commit 8040f29

File tree

1 file changed

+65
-94
lines changed

1 file changed

+65
-94
lines changed

examples/alacarte/src/app.jsx

Lines changed: 65 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -2,144 +2,115 @@ import React from 'react';
22
import { render } from 'react-dom';
33
import Most, { connect } from 'react-most'
44
import {
5+
Expr,
6+
Val,
57
injectorFrom,
68
interpreterFrom,
79
interpretExpr,
8-
Functor,
910
interpreterFor,
10-
inject,
11-
supTypeSameAs,
11+
isInjectedBy,
1212
} from 'alacarte.js'
1313

1414
const compose = f => g => x=> f(g(x))
1515

16-
// Data Types of Exprs
17-
function Add(value0) {
18-
this.value0 = value0
19-
}
20-
21-
function Lit(value0) {
22-
this.value0 = value0
23-
}
24-
function Over(value0, value1) {
25-
this.value0 = value0
26-
this.value1 = value1
27-
}
28-
29-
// Their Functor Instance
30-
const functorLit = new Functor(f => v => new Lit(v.value0))
31-
const functorAdd = new Functor(f => v => new Add(f(v.value0)))
32-
const functorOver = new Functor(f => v => new Over(f(v.value0), f(v.value1)))
33-
34-
// Injectors
35-
function injectLit(injector) {
36-
return n => inject(injector(functorLit))(new Lit(n))
37-
}
38-
39-
function injectAdd(injector) {
40-
return (a, b) => inject(injector(functorAdd))(new Add(a, b))
41-
}
42-
43-
function injectOver(injector) {
44-
return (a, b) => inject(injector(functorOver))(new Over(a, b))
45-
}
16+
let {Add, Over} = Expr.create({
17+
Add: ['fn'],
18+
Over: ['prop', 'fn']
19+
})
4620

4721
// Instances of Interpreters
48-
const evalAdd = interpreterFor(functorAdd, function (v) {
49-
return x => x + v.value0(x)
22+
const evalAdd = interpreterFor(Add, function (v) {
23+
return x => x + v.fn(x)
5024
});
5125

52-
const evalLit = interpreterFor(functorLit, function (v) {
53-
return ()=> v.value0
26+
const evalVal = interpreterFor(Val, function (v) {
27+
return ()=> v.value
5428
});
5529

56-
const evalOver = interpreterFor(functorOver, function (v) {
30+
const evalOver = interpreterFor(Over, function (v) {
5731
let newstate = {}
58-
let value = v.value0()
59-
return state => (newstate[value] = v.value1(state[value]), newstate)
32+
let prop = v.prop()
33+
return state => (newstate[prop] = v.fn(state[prop]), newstate)
6034
});
6135

62-
// Compose a Interpreter which can interpret Lit, Add, Over
63-
let interpreter = interpreterFrom([evalLit, evalAdd, evalOver])
64-
// Injector that can inject Lit, Add, Over
65-
let injector = injectorFrom([functorLit, functorAdd, functorOver])
66-
67-
// Expressions
68-
let add = injectAdd(injector)
69-
let lit = injectLit(injector)
70-
let over = injectOver(injector)
71-
7236
// You can define any Interpreters you want, instead of eval value, this interpreter print the expressions
73-
const printAdd = interpreterFor(functorAdd, function (v) {
74-
return `(_ + ${v.value0})`
37+
const printAdd = interpreterFor(Add, function (v) {
38+
return `(_ + ${v.fn})`
7539
});
7640

77-
const printLit = interpreterFor(functorLit, function (v) {
78-
return v.value0.toString()
41+
const printVal = interpreterFor(Val, function (v) {
42+
return v.value.toString()
7943
});
8044

81-
const printOver = interpreterFor(functorOver, function (v) {
82-
return `over ${v.value0} do ${v.value1}`
45+
const printOver = interpreterFor(Over, function (v) {
46+
return `over ${v.prop} do ${v.fn}`
8347
});
8448

85-
const printer = interpreterFrom([printLit, printAdd, printOver])
49+
const printer = interpreterFrom([printVal, printAdd, printOver])
8650

8751
const CounterView = props => (
8852
<div>
89-
<button onClick={props.actions.dec}>-</button>
53+
<button onClick={props.actions.dec}>{props.dec}</button>
9054
<span>{props.count}</span>
91-
<button onClick={props.actions.inc}>+</button>
55+
<button onClick={props.actions.inc}>{props.inc}</button>
9256
</div>
9357
)
9458

9559
CounterView.defaultProps = { count: 1 };
9660

9761
const counterable = connect((intent$) => {
98-
return {
99-
sink$: intent$.filter(supTypeSameAs(injector)) // <-- filter only expressions compose with type Lit :+: Add :+: Over
100-
.tap(compose(console.log)(interpretExpr(printer))) // interpret with printer
101-
.map(interpretExpr(interpreter)), // interpret with interpreter(eval value)
102-
inc: () => over(lit('count'), add(add(lit(1)))), // you can compose expressions to achieve your bussiness
103-
dec: () => injectOver(injectorFrom([functorLit, functorOver]))(lit('count'), add(lit(-1))) // a expr with different type like Lit :+: Over will be filtered out(do nothing here)
104-
}
62+
// Compose a Interpreter which can interpret Lit, Add, Over
63+
let interpreter = interpreterFrom([evalVal, evalAdd, evalOver])
64+
// Injector that can inject Lit, Add, Over
65+
let injector = injectorFrom([Val, Add, Over])
66+
67+
let [val, add, over] = injector.inject()
68+
69+
return {
70+
sink$: intent$.filter(isInjectedBy(injector)) // <-- filter only expressions compose with type Lit :+: Add :+: Over
71+
.tap(compose(console.log)(interpretExpr(printer))) // interpret with printer
72+
.map(interpretExpr(interpreter)), // interpret with interpreter(eval value)
73+
inc: () => over(val('count'), add(val(1))), // you can compose expressions to achieve your bussiness
74+
dec: () => {
75+
let aNewInjector = injectorFrom([Val, Add, Over])
76+
let [val, add, over] = aNewInjector.inject()
77+
return over(val('count'), add(val(-1)))
78+
} // only a expr with same type and order can be interpret
79+
}
10580
})
10681

82+
// a new mult expr is add without modify any of the current code
83+
let {Mult} = Expr.create({
84+
Mult: ['fn'],
85+
})
86+
const evalMult = interpreterFor(Mult, function (v) {
87+
return x => x * v.fn(x)
88+
});
89+
90+
let printMult = interpreterFor(Mult, function (v) {
91+
return `(_ * ${v.fn})`
92+
});
93+
10794
const multable = connect((intent$) => {
108-
function Mult(value0) {
109-
this.value0 = value0
110-
}
111-
const functorMult = new Functor(f => v => new Mult(f(v.value0)))
112-
function injectMult(injector) {
113-
return (a, b) => inject(injector(functorMult))(new Mult(a, b))
114-
}
115-
const evalMult = interpreterFor(functorMult, function (v) {
116-
return x => x * v.value0(x)
117-
});
118-
let injector = injectorFrom([functorLit, functorAdd, functorOver, functorMult])
119-
let add = injectAdd(injector)
120-
let lit = injectLit(injector)
121-
let mult = injectMult(injector)
122-
let over = injectOver(injector)
123-
let printMult = interpreterFor(functorMult, function (v) {
124-
return `(_ * ${v.value0})`
125-
});
126-
let interpreter = interpreterFrom([evalLit, evalAdd, evalOver, evalMult])
127-
const printer = interpreterFrom([printLit, printAdd, printOver, printMult])
95+
let injector = injectorFrom([Val, Add, Over, Mult])
96+
let [val, add, over, mult] = injector.inject()
97+
let interpreter = interpreterFrom([evalVal, evalAdd, evalOver, evalMult])
98+
let printer = interpreterFrom([printVal, printAdd, printOver, printMult])
12899
return {
129-
sink$: intent$.filter(supTypeSameAs(injector))
130-
.tap(compose(console.log)(interpretExpr(printer)))
131-
.map(interpretExpr(interpreter)),
132-
inc: () => over(lit('count'), mult(add(lit(1)))),
100+
sink$: intent$.filter(isInjectedBy(injector))
101+
.tap(compose(console.log)(interpretExpr(printer)))
102+
.map(interpretExpr(interpreter)),
103+
inc: () => over(val('count'), mult(val(2))),
104+
dec: () => over(val('count'), mult(val(0.5))),
133105
}
134106
})
135107
const Counter = counterable(CounterView)
136-
const Counter2 = multable(CounterView)
108+
const Multer = multable(CounterView)
137109
render(
138110
<Most>
139111
<div>
140-
<Counter />
141-
<Counter2 />
112+
<Counter inc="+1" dec="-1" />
113+
<Multer inc="*2" dec="/2"/>
142114
</div>
143-
144115
</Most>
145116
, document.getElementById('app'));

0 commit comments

Comments
 (0)