[Functional Programming] Combine State Dependent Transactions with the State ADT (composeK to replac...

When developing a Finite State Machine, it is often necessary to apply multiple transitions in tandem. To accomplish this in most Redux work flows requires at best, implementing multiple action handlers in separate reducers; or at worse, the need to duplicate logic for similar action handlers, sometime across multiple files. However when using a State ADT, we can easily combine these independent transitions by simply chain-ing multiple discrete transitions into one transaction. We demonstrate this interface by transitioning two portions of related state with one transaction.

 

const { curry, compose, State, mapProps, composeK } = require("crocks");

const { modify } = State;

const state = {
  left: 8,
  moves: 0
};

const inc = x => x + 1;
const dec = x => x - 1;

const clamp = (min, max) => x => Math.min(Math.max(min, x), max);
const clampAfter = curry((min, max, fn) =>
  compose(
    clamp(min, max),
    fn
  )
);
const over = (key, fn) => modify(mapProps({ [key]: fn }));

const limitMoves = clampAfter(0, 8);

const decLeft = () => over("left", limitMoves(dec));
const incMoves = () => over("moves", limitMoves(inc));

// Then there are a series of chain functions, using composeK
/**
 * replace: 
 *  decLeft()
 *      .chain(decLeft)
 *      .chain(decLeft)
 *      .chain(decLeft)
 *      .chain(incMoves)
 *      .chain(incMoves)
 */
const applyMove = composeK(
    incMoves, incMoves, decLeft, decLeft, decLeft
)

const res = applyMove()
  .execWith(state);
console.log(res); //{ left: 5, moves: 2 }

 

 

Another example:

const state = {
    cards: [
        {id: 'green-square', color: 'green', shape: 'square'},
        {id: 'orange-square', color: 'orange', shape: 'square'},
        {id: 'blue-square', color: 'blue', shape: 'triangle'}
    ],
    left: 8,
    moves: 0
}

const {State, when, assign, map, mapProps, propEq} = require('crocks');
const {modify} = State;

const markSelected = id => assignBy(propEq('id', id), {selected: true})
const assignBy = (pred, obj) => when(pred, assign(obj));
const over = (key, fn) => modify(mapProps({ [key]: fn }));

const selectCard = id => over('cards', map(markSelected(id)))



console.log(
    JSON.stringify(
        selectCard('green-square').execWith(state),
        null,
        2
    )
);


/*
// Using Ramda to implememnt the same logic
const {compose, map, propOr, when, propEq, mergeLeft} = require('ramda');

const markAsSelected = (id) => when(propEq('id', id), mergeLeft({selected: true}))
const over = (key, fn) => compose(map(fn), propOr([], key));

const selectCard2 = (id) => over('cards', markAsSelected(id))

console.log(
    JSON.stringify(
        selectCard2('green-square')(state),
        null,
        2
    )
)*/

 

转载于:https://www.cnblogs.com/Answer1215/p/10235148.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值