Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Typeclasses #52

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
jcouyang merged 28 commits into master from typeclasses
Oct 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
377532b
ts strict mode
jcouyang Oct 1, 2017
f9933f5
3.0.1
jcouyang Oct 1, 2017
1f657b7
dedup makefile
jcouyang Oct 1, 2017
a5f6fa7
add typeclasses
jcouyang Oct 4, 2017
b57e510
poly typeclasses
jcouyang Oct 6, 2017
c616a8a
update state with typeclasses
jcouyang Oct 7, 2017
0277764
typeclass implement for xs/rx and xs/most
jcouyang Oct 8, 2017
3242d14
add test for new fantasyX
jcouyang Oct 8, 2017
7654a87
able to create xstream from promise and flatmap
jcouyang Oct 9, 2017
95a4582
add types for react dom
jcouyang Oct 10, 2017
68ecd4c
xstream semigroup
jcouyang Oct 18, 2017
7523700
semigroup test
jcouyang Oct 18, 2017
c14cb7c
implement FantasyX typeclasses
jcouyang Oct 18, 2017
4a1a4a2
fantasy example integration test
jcouyang Oct 18, 2017
890aff0
example 3
jcouyang Oct 18, 2017
ac9c4f7
traversable
jcouyang Oct 19, 2017
dd9b5b8
traversable example
jcouyang Oct 19, 2017
f0714e8
foldable
jcouyang Oct 19, 2017
4a20a6f
fold and merge
jcouyang Oct 19, 2017
0654ced
4.0.0
jcouyang Oct 19, 2017
b25bc5f
expose Xstream and FantasyX
jcouyang Oct 19, 2017
5ca3db1
4.0.1
jcouyang Oct 19, 2017
792d21d
remove rx and most from depends on typeclasses
jcouyang Oct 20, 2017
8cb5f61
4.0.2
jcouyang Oct 20, 2017
115c0e3
throw Error when no metadata found, fix xstream apply
jcouyang Oct 20, 2017
86e0f71
4.0.3
jcouyang Oct 20, 2017
94013c9
dont shim reflect metadata
jcouyang Oct 20, 2017
6ac7c19
4.0.4
jcouyang Oct 20, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .editorconfig
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ root = true
indent_style = tab
indent_size = 2

[*.ts, *.tsx]
[*.{ts,tsx}]
indent_style = space
indent_size = 2
end_of_line = lf
Expand Down
38 changes: 23 additions & 15 deletions Makefile
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -1,41 +1,49 @@
docs = ./docs/**/*
docsdir = ./docs/**/*
browserify = ./node_modules/.bin/browserify
watchify = ./node_modules/.bin/watchify
uglify = ./node_modules/.bin/uglifyjs

test: unit integrate

build: lib/**/*.js

lib/**/*.js: src/**/*.ts
tsc

lib/%.js: src/%.ts
tsc

all: docs/src/main/tut/examples/example.js browser
all: test dist

.PHONY: test
test: lib/**/*.js test/*.js docs/src/main/tut/examples/example.js
.PHONY: test build unit integrate dist docs docs/publish

unit: build
yarn test

integrate: build test/*.js docs/src/main/tut/examples/example.js
mocha test/test.js

docs/src/main/tut/examples/example.js: docs/src/main/tut/examples/example.tsx
$(browserify) -p [tsify -p tsconfig.examples.json] docs/src/main/tut/examples/example.tsx -o docs/src/main/tut/examples/example.js

watch/example: docs/src/main/tut/examples/example.tsx
$(watchify) -p [tsify -p tsconfig.examples.json] -t envify docs/src/main/tut/examples/example.tsx -dv -o docs/src/main/tut/examples/example.js

browser: dist/xreact.min.js dist/xreact-most.min.js dist/xreact-rx.min.js

dist/xreact.js: lib/index.js
env NODE_ENV=production $(browserify) -t browserify-shim -t envify -x ./lib/xs lib/index.js -s xreact -o $@
dist: dist/xreact.min.js dist/xreact-most.min.js dist/xreact-rx.min.js

dist/xreact-most.js: lib/xs/most.js
env NODE_ENV=production $(browserify) -t browserify-shim -t envify -r ./lib/xs lib/xs/most.js -o $@
dist/xreact.js: lib/index.js dist/xreact-most.js dist/xreact-rx.js
env NODE_ENV=production $(browserify) -t browserify-shim -t envify -x ./lib/xs $< -s xreact -o $@

dist/xreact-rx.js: lib/xs/rx.js
env NODE_ENV=production $(browserify) -t browserify-shim -t envify -r ./lib/xs lib/xs/rx.js -o $@
dist/xreact-%.js: lib/xs/%.js
env NODE_ENV=production $(browserify) -t browserify-shim -t envify -r ./lib/xs $< -o $@

dist/%.min.js: dist/%.js
env NODE_ENV=production $(uglify) -c dead_code $(basename $(basename $@)).js -o $@

docs: $(docs)
sbt makeMicrosite
docs: $(docsdir)
sbt "project docs" makeMicrosite

docs/publish: $(docs)
docs/publish: $(docsdir)
sbt "project docs" publishMicrosite

clean:
Expand Down
13 changes: 11 additions & 2 deletions docs/src/main/tut/Get-Started.md
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ position: 1
Sorry we don't have a **book** to document how to use xreact, and I don't really need to,
there's only 3 things you should notice when using xreact, I'll explain by a simple counter app.

<iframe src="https://www.webpackbin.com/bins/-KsSVkmGpVrLlwylSrkE" frameborder="0" width="100%" height="500"></iframe>
<p data-height="265" data-theme-id="light" data-slug-hash="gGqvBW" data-default-tab="js,result" data-user="jcouyang" data-embed-version="2" data-pen-title="XREACT" class="codepen">See the Pen <a href="https://codepen.io/jcouyang/pen/gGqvBW/">XREACT</a> by Jichao Ouyang (<a href="https://codepen.io/jcouyang">@jcouyang</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

### 1. Define a simple stateless View component

Expand Down Expand Up @@ -101,4 +102,12 @@ render(

If you are TypeScript user and want to enjoy a type safe counter app, it's simple to do so since xReact is written 100% in TypeScript.

<iframe src="https://www.webpackbin.com/bins/-KsSYQVTkFjd_MQon3b9" frameborder="0" width="100%" height="500"></iframe>
<p data-height="265" data-theme-id="light" data-slug-hash="jGdzYR" data-default-tab="js,result" data-user="jcouyang" data-embed-version="2" data-pen-title="XREACT Counter in TypeScript" class="codepen">See the Pen <a href="https://codepen.io/jcouyang/pen/jGdzYR/">XREACT Counter in TypeScript</a> by Jichao Ouyang (<a href="https://codepen.io/jcouyang">@jcouyang</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

## Fantasy 🌈 Counter

If you come from 🌈 fantasy land, you cound try fantasy version of xreact in less verbose and more functional scheme. [More about FantasyX](./Fantasy.html)

<p data-height="381" data-theme-id="light" data-slug-hash="wrNjNM" data-default-tab="js,result" data-user="jcouyang" data-embed-version="2" data-pen-title="XREACT FANTASY COUNTER" class="codepen">See the Pen <a href="https://codepen.io/jcouyang/pen/wrNjNM/">XREACT FANTASY COUNTER</a> by Jichao Ouyang (<a href="https://codepen.io/jcouyang">@jcouyang</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
177 changes: 94 additions & 83 deletions docs/src/main/tut/examples/example.tsx
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -1,44 +1,54 @@
import * as React from 'react';
import { render } from 'react-dom';
import '../../../../../src/xs/rx'
import { pure, lift2, X, xinput, fromEvent, traverse, fold } from '../../../../../src'
import { Applicative, lift2,Semigroup, Functor, map, Traversable, FlatMap } from '../../../../../src/fantasy'
import {X} from '../../../../../src'
function xmount(component, dom) { render(React.createFactory(X)({}, component), dom) }

let mult = (x:number,y: number) => x * y
let Xeg1 = lift2(mult)(pure(6), pure(5))
let Xeg1 = lift2<"FantasyX",number, number, number>(mult)(Applicative.FantasyX.pure(6), Applicative.FantasyX.pure(5))

let ViewEg1 = props => <p className="result">{props.product}</p>

let Eg1 = Xeg1.map(a=>({product: a})).apply(ViewEg1)
let Eg1 = Functor.FantasyX.map(a=>({product: a}), Xeg1).apply(ViewEg1)

xmount(<Eg1/>, document.getElementById('eg1') )

import {Xstream} from '../../../../../src/fantasy/xstream';

function strToInt(x) {return ~~x}
type Intent = {type:string, value:number}
let XSinput1 = Xstream.fromEvent('change', 'n1', '5')
let XSinput2 = Xstream.fromEvent('change', 'n2', '6')

let Xeg2 = lift2(mult)(
fromEvent('change', 'n1', '5').map(strToInt),
fromEvent('change', 'n2', '6').map(strToInt)
)
let Xeg2 = lift2<"Xstream", number, number, number>(mult)(
Functor.Xstream.map(strToInt, XSinput1),
Functor.Xstream.map(strToInt, XSinput2)
).toFantasyX()
.map(x=>({product: x}))

let ViewEg2 = props => <section>
<p><input type="number" name="n1" onChange={props.actions.fromEvent} defaultValue="5"/></p>
<p><input type="number" name="n2" onChange={props.actions.fromEvent} defaultValue="6"/></p>
<p><span className="result">{props.product}</span></p>
</section>
<p><input type="number" name="n1" onChange={props.actions.fromEvent} defaultValue="5"/></p>
<p><input type="number" name="n2" onChange={props.actions.fromEvent} defaultValue="6"/></p>
<p><span className="result">{props.product}</span></p>
</section>

let Eg2 = Xeg2.map(a=>({product: a})).apply(ViewEg2)
let Eg2 = Xeg2.apply(ViewEg2)

xmount(<Eg2/>, document.getElementById('eg2') )

let Xeg3 = fromEvent('change', 'firstName', 'Jichao')
.concat(pure(' '))
.concat(fromEvent('change', 'lastName', 'Ouyang'))

let Xeg3 = Semigroup.Xstream.concat(
Semigroup.Xstream.concat(
Xstream.fromEvent('change', 'firstName', 'Jichao'),
Applicative.Xstream.pure(' ')
),
Xstream.fromEvent('change', 'lastName', 'Ouyang')
).toFantasyX()
let ViewEg3 = props => <section>
<p><input type="text" name="firstName" onChange={props.actions.fromEvent} defaultValue="Jichao" /></p>
<p><input type="text" name="lastName" onChange={props.actions.fromEvent} defaultValue="Ouyang"/></p>
<p><span className="result">{props.semigroup}</span></p>
</section>
<p><input type="text" name="firstName" onChange={props.actions.fromEvent} defaultValue="Jichao" /></p>
<p><input type="text" name="lastName" onChange={props.actions.fromEvent} defaultValue="Ouyang"/></p>
<p><span className="result">{props.semigroup}</span></p>
</section>

let Eg3 = Xeg3.map(a=>({semigroup: a})).apply(ViewEg3)

Expand All @@ -48,10 +58,11 @@ function sum(list){
return list.reduce((acc,x)=> acc+x, 0)
}
let list = ['1', '2', '3', '4', '5', '6', '7']
let Xeg4 = traverse(
(defaultVal, index)=>(fromEvent('change', 'traverse'+index, defaultVal)),
list
).map(xs=>xs.map(strToInt))
let Xeg4 = Traversable.Array.traverse<'Xstream', string, string>('Xstream')(
(defaultVal, index) => (Xstream.fromEvent('change', 'traverse' + index, defaultVal)),
list
).toFantasyX()
.map(xs => xs.map(strToInt))
.map(sum)

let ViewEg4 = props => <section>
Expand All @@ -67,91 +78,91 @@ let Eg4 = Xeg4.map(a=>({sum: a})).apply(ViewEg4)
xmount(<Eg4/>, document.getElementById('eg4') )

function bmiCalc(weight, height) {
return {
weight: weight,
height: height,
result:fetch(`https://gist.github.com.ru/jcouyang/edc3d175769e893b39e6c5be12a8526f?height=${height}&weight=${weight}`)
.then(resp => resp.json())
.then(json => json.result)
}
return fetch(`https://gist.github.com.ru/jcouyang/edc3d175769e893b39e6c5be12a8526f?height=${height}&weight=${weight}`)
.then(resp => resp.json())
.then(json => json.result)
}

let Xeg5 = lift2(bmiCalc)(
fromEvent('change', 'weight', '70'),
fromEvent('change', 'height', '175')
let xweigth = Xstream.fromEvent('change', 'weight', '70')
let xheight = Xstream.fromEvent('change', 'height', '175')

let promiseXstream = lift2<"Xstream", string, string, Promise<any>>(bmiCalc)(
xweigth,
xheight
)

let Xeg5 = FlatMap.Xstream.flatMap(Xstream.fromPromise, promiseXstream)
.toFantasyX()

let ViewEg5 = props => (
<div>
<label>Height: {props.height} cm
<input type="range" name="height" onChange={props.actions.fromEvent} min="150" max="200" defaultValue={props.height} />
</label>
<label>Weight: {props.weight} kg
<input type="range" name="weight" onChange={props.actions.fromEvent} min="40" max="100" defaultValue={props.weight} />
</label>
<p>HEALTH: <span>{props.health}</span></p>
<p>BMI: <span className="result">{props.bmi}</span></p>
</div>
)

let ViewEg5 = props => (
<div>
<label>Height: {props.height} cm
<input type="range" name="height" onChange={props.actions.fromEvent} min="150" max="200" defaultValue={props.height} />
</label>
<label>Weight: {props.weight} kg
<input type="range" name="weight" onChange={props.actions.fromEvent} min="40" max="100" defaultValue={props.weight} />
</label>
<p>HEALTH: <span>{props.health}</span></p>
<p>BMI: <span className="result">{props.bmi}</span></p>
</div>
)

let Eg5 = Xeg5.apply(ViewEg5)
let Eg5 = Xeg5.apply(ViewEg5)

xmount(<Eg5/>, document.getElementById('eg5') )

let Xeg6 = fold(
(acc:number,i: number) => acc+i,
0,
fromEvent('click', 'increment').map(x=>1)
)
let Xeg6 = Xstream.fromEvent('click', 'increment')
.toFantasyX<{count:number}>()
.map(x => 1)
.foldS((acc, a) => {
return { count: (acc.count||0) + a }})

let ViewEg6 = props => <p>
<span className="result">{props.count}</span>
<input type="button" name="increment" value="+1" onClick={e=>props.actions.fromEvent(e)} />
</p>
<span className="result">{props.count || 0}</span>
<input type="button" name="increment" value="+1" onClick={e=>props.actions.fromEvent(e)} />
</p>

let Eg6 = Xeg6.map(a=>({count: a})).apply(ViewEg6)
let Eg6 = Xeg6.apply(ViewEg6)

xmount(<Eg6/>, document.getElementById('eg6') )

let Xeg7 = fold(
(acc:number,i: number) => acc+i,
0,
fromEvent('click', 'increment').map(x=>1)
.merge(
fromEvent('click', 'decrement').map(x=>-1)
)
)
let Xeg7 = Xstream.fromEvent('click', 'decrement')
.toFantasyX<{count:number}>()
.map(x => -1)
.foldS((acc, a) => {
return { count: (acc.count||0) + a }})

let ViewEg7 = props => <p>
<input type="button" name="decrement" value="-" onClick={e=>props.actions.fromEvent(e)} />
<span className="result">{props.count}</span>
<input type="button" name="increment" value="+" onClick={e=>props.actions.fromEvent(e)} />
</p>
let ViewEg7 = props => <p>
<input type="button" name="decrement" value="-" onClick={e=>props.actions.fromEvent(e)} />
<span className="result">{props.count || 0}</span>
<input type="button" name="increment" value="+" onClick={e=>props.actions.fromEvent(e)} />
</p>

let Eg7 = Xeg7.map(a=>({count: a})).apply(ViewEg7)
let Eg7 = Xeg7.merge(Xeg6).apply(ViewEg7)

xmount(<Eg7/>, document.getElementById('eg7') )

const actions = ['-1', '+1', 'reset']
let Xeg8 = fold(
(acc, i) => {
switch(i) {
case '-1': return acc-1
case '+1': return acc+1
case 'reset': return 0
default: acc
let Xeg8 =
actions.map((action)=>Xstream.fromEvent('click', action).toFantasyX<{count:number}>())
.reduce((acc,a)=>acc.merge(a))
.foldS((acc, i) => {
acc.count = acc.count || 0
switch(i) {
case '-1': return {count: acc.count -1}
case '+1': return {count: acc.count +1}
case 'reset': return {count: 0}
default: acc
}
}
},
0,
actions.map((action)=>fromEvent('click', action))
.reduce((acc,a)=>acc.merge(a)))
)

let ViewEg8 = props => <p>
<span className="result">{props.count}</span>
{actions.map(action=>
<input type="button" name={action} value={action} onClick={e=>props.actions.fromEvent(e)} />)}
</p>

let Eg8 = Xeg8.map(a=>({count: a})).apply(ViewEg8)
let Eg8 = Xeg8.apply(ViewEg8)

xmount(<Eg8/>, document.getElementById('eg8') )
Loading

AltStyle によって変換されたページ (->オリジナル) /