# XReact Fantasy

xReact is a Functional library that can integrate FRP lib rxjs or mostjs into react. But there’re still too many verbose you need to care while modeling UI components.

The implement of Fantasy Land, which will change the way you model and implement UI entirely.

The idea of FantasyX is highly inspired by flare by purescript

`lift`

Let’s use List as example, what `lift`

does is very similar to `map`

```
const f = x => x + 1
[1,2,3].map(f) // => [2,3,4]
```

It simply map `f`

to every items in the list. While if we do it another way around:

```
const lf = lift(f)
lf([1,2,3]) // => [2,3,4]
```

Now `lf`

can take a list, apply `f`

to each item, and return a new list. So `lf`

is just a lifted version of `f`

. You should notice that both lift and map transform `x => x + 1`

which should only able to apply to `Number`

, to a function that can apply to `Array<Number>`

We can now (from v2.3.0) lift a normal function(takes value and return value) to a FantasyX level function(take FantasyX and return FantasyX) as well.

Let’s take a look at a really simple example, multiply 2 numbers.

```
// Number -> Number -> Number
function mult(a, b) {
return a * b
}
mult(1, 2)
```

But if we need a React Component that multiply 2 numbers from 2 input boxes, how complicated it could be?

Now you get simply get a free FantasyX from just any normal function, via `lift`

.

```
// FantasyX -> FantasyX -> FantasyX
let xMult = lift2(mult)
```

`mult`

need 2 arguments, that’s why we use `lift2`

here.

Now that we have on function `xMult`

that can turn 2 FantasyX into one, lets do this:

```
let XMult = xMult(xinput('a'), xinput('b'))
```

and we got a new FantasyX `XMult`

with the computation built in.

`xinput`

is an FantasyX abstraction of input box.

All we have so far was just a FantasyX `XMult`

with computation composed inside, and we need a View to display and interact with. Here comes a really simple Stateless Component

```
const View = props => (
<div>
<input name="a" onChange={props.actions.fromEvent} defaultValue={props.a}/>
<input name="b" onChange={props.actions.fromEvent} defaultValue={props.b}/>
<div>{props.output}</div>
</div>
)
View.defaultProps = { a: "", b: "",output:""}
```

apply XMult to View then we’ll get a React Component

```
let Mult = XMult.apply(View)
```

https://www.webpackbin.com/bins/-KoGxSJ-3pOi4DicUvaq

## Functor

FantasyX also implemented Functor, so we can transform one FantasyX to another

For example, from `XMult`

, we could simply transform it into a `XMMP`

with new computation

```
let XMMP = XMult.map((s) => ({output: s.output * s.output}))
```

it’s just like mapping on a list

```
[1,2,3].map(x=>x*x)
// [2,4,6]
```

https://www.webpackbin.com/bins/-Kss6m5ORK74CObhAPqB

## Monoid

It’s actually Semigroup, but if we have a ID FantasyX, we have Monoid, an Identity FantasyX make sense in that the computation inside is just Identity.

Anyway, let’s see how can we combine two FantasyX together

```
let XCOMBINE = XMMP.concat(XMult)
```

仅此, 我们就得到了一个同时具有 XMMP 与 XMult 行为的 FantasyX

当然, 因为他们都会修改 `state.output`

, 合并到一起会导致冲突, 我们稍微修改下 XMMP

```
let XMMP = XMult.map((s) => ({output2: s.output * s.output}))
```

nothing special just like how you concat two Arrays

https://www.webpackbin.com/bins/-Kss6m5ORK74CObhAPqB

Check out a more complicated BMI Calculator: