@@ -2,144 +2,115 @@ import React from 'react';
22import { render } from 'react-dom' ;
33import Most , { connect } from 'react-most'
44import {
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
1414const 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
8751const 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
9559CounterView . defaultProps = { count : 1 } ;
9660
9761const 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+
10794const 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} )
135107const Counter = counterable ( CounterView )
136- const Counter2 = multable ( CounterView )
108+ const Multer = multable ( CounterView )
137109render (
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