@@ -12,6 +12,8 @@ import {
1212} from 'alacarte.js'
1313
1414const compose = f => g => x => f ( g ( x ) )
15+
16+ // Data Types of Exprs
1517function Add ( value0 ) {
1618 this . value0 = value0
1719}
@@ -24,10 +26,12 @@ function Over(value0, value1) {
2426 this . value1 = value1
2527}
2628
29+ // Their Functor Instance
2730const functorLit = new Functor ( f => v => new Lit ( v . value0 ) )
2831const functorAdd = new Functor ( f => v => new Add ( f ( v . value0 ) ) )
2932const functorOver = new Functor ( f => v => new Over ( f ( v . value0 ) , f ( v . value1 ) ) )
3033
34+ // Injectors
3135function injectLit ( injector ) {
3236 return n => inject ( injector ( functorLit ) ) ( new Lit ( n ) )
3337}
@@ -40,30 +44,32 @@ function injectOver(injector) {
4044 return ( a , b ) => inject ( injector ( functorOver ) ) ( new Over ( a , b ) )
4145}
4246
43- function injectState ( injector ) {
44- return n => inject ( injector ( functorState ) ) ( new State ( n ) )
45- }
46-
47+ // Instances of Interpreters
4748const evalAdd = interpreterFor ( functorAdd , function ( v ) {
48- return x => x + v . value0
49+ return x => x + v . value0 ( x )
4950} ) ;
5051
5152const evalLit = interpreterFor ( functorLit , function ( v ) {
52- return v . value0
53+ return ( ) => v . value0
5354} ) ;
5455
5556const evalOver = interpreterFor ( functorOver , function ( v ) {
5657 let newstate = { }
57- return state => ( newstate [ v . value0 ] = v . value1 ( state [ v . value0 ] ) , newstate )
58+ let value = v . value0 ( )
59+ return state => ( newstate [ value ] = v . value1 ( state [ value ] ) , newstate )
5860} ) ;
5961
62+ // Compose a Interpreter which can interpret Lit, Add, Over
6063let interpreter = interpreterFrom ( [ evalLit , evalAdd , evalOver ] )
64+ // Injector that can inject Lit, Add, Over
6165let injector = injectorFrom ( [ functorLit , functorAdd , functorOver ] )
6266
67+ // Expressions
6368let add = injectAdd ( injector )
6469let lit = injectLit ( injector )
6570let over = injectOver ( injector )
6671
72+ // You can define any Interpreters you want, instead of eval value, this interpreter print the expressions
6773const printAdd = interpreterFor ( functorAdd , function ( v ) {
6874 return `(_ + ${ v . value0 } )`
6975} ) ;
@@ -77,6 +83,7 @@ const printOver = interpreterFor(functorOver, function (v) {
7783} ) ;
7884
7985const printer = interpreterFrom ( [ printLit , printAdd , printOver ] )
86+
8087const CounterView = props => (
8188 < div >
8289 < button onClick = { props . actions . dec } > -</ button >
@@ -85,21 +92,54 @@ const CounterView = props => (
8592</ div >
8693)
8794
88- CounterView . defaultProps = { count : 0 } ;
95+ CounterView . defaultProps = { count : 1 } ;
8996
9097const counterable = connect ( ( intent$ ) => {
9198 return {
92- sink$ : intent$ . filter ( supTypeSameAs ( injector ) ) . tap ( compose ( console . log ) ( interpretExpr ( printer ) ) )
93- . map ( interpretExpr ( interpreter ) ) ,
94- inc : ( ) => over ( lit ( 'count' ) , add ( lit ( 1 ) ) ) ,
95- dec : ( ) => injectOver ( injectorFrom ( [ functorLit , functorOver ] ) ) ( lit ( 'count' ) , add ( lit ( - 1 ) ) )
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)
96104 }
97105} )
98106
107+ 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 ] )
128+ 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 ) ) ) ) ,
133+ }
134+ } )
99135const Counter = counterable ( CounterView )
100-
136+ const Counter2 = multable ( CounterView )
101137render (
102- < Most >
138+ < Most >
139+ < div >
103140 < Counter />
141+ < Counter2 />
142+ </ div >
143+
104144 </ Most >
105145 , document . getElementById ( 'app' ) ) ;
0 commit comments