By using the State ADT to define how our application state transitions over time, we clear up the need for a some of the boilerplate that we typically need for a solid Redux integration. We can keep our action names and creators in the same file as the reducer they are used in, as we no longer need to have separate files to hand the same action across different portions of our state.

We will build our a single reducer that will handle the integration with Redux and organize our State ADT based reducers in their own files and bring them into our main reducer to handle running our state transitions and the cases where we do not have an transition for a given action.

// Action a :: {type: string, payload: a}
// createAction :: String -> a -> Action a
const createAction = type => payload => ({type, payload});
const SELECT_CARD = 'SELECT_CARD';
const selectCard = createAction(SELECT_CARD); // reducer :: (State, a) -> (State AppState ()) | Null
const reducer = (prevState, {type, payload}) => {
let result;
switch(type) {
case SELECT_CARD:
result = feedback(payload);
break;
default:
result = null;
} return isSameType(State, result) ? result.execWith(prevState): prevState;
} const sillyVerb = createAction('SILLY_VERB'); console.log(
reducer(
state,
selectCard('green-square')
)
)

If we pass the right action, it will return the result, if a bad action, it keep the prev state untouched.

---

const {prop, isSameType, State, omit, curry, converge,map, composeK, liftA2, equals, constant,option, chain, mapProps, find, propEq, isNumber, compose, safe} = require('crocks');
const {get, modify, of} = State; const state = {
cards: [
{id: 'green-square', color: 'green', shape: 'square'},
{id: 'orange-square', color: 'orange', shape: 'square'},
{id: 'blue-triangle', color: 'blue', shape: 'triangle'}
],
hint: {
color: 'green',
shape: 'square'
},
isCorrect: null,
rank: 2
}
const inc = x => x + 1;
const dec = x => x - 1;
const incOrDec = b => b ? dec : inc;
const clamp = (min, max) => x => Math.min(Math.max(min, x), max);
const clampAfter = curry((min, max, fn) => compose(clamp(min, max), fn))
const limitRank = clampAfter(0, 4);
const over = (key, fn) => modify(mapProps({[key]: fn}))
const getState = key => get(prop(key));
const liftState = fn => compose(
of,
fn
)
const getCard = id => getState('cards')
.map(chain(find(propEq('id', id))))
.map(option({}))
const getHint = () => getState('hint')
.map(option({}))
const cardToHint = composeK(
liftState(omit(['id'])),
getCard
)
const validateAnswer = converge(
liftA2(equals),
cardToHint,
getHint
)
const setIsCorrect = b => over('isCorrect', constant(b));
const adjustRank = compose(limitRank, incOrDec);
const updateRank = b => over('rank', adjustRank(b));
const applyFeedback = converge(
liftA2(constant),
setIsCorrect,
updateRank
)
const feedback = composeK(
applyFeedback,
validateAnswer
)
// Action a :: {type: string, payload: a}
// createAction :: String -> a -> Action a
const createAction = type => payload => ({type, payload});
const SELECT_CARD = 'SELECT_CARD';
const selectCard = createAction(SELECT_CARD); // reducer :: (State, a) -> (State AppState ()) | Null
const reducer = (prevState, {type, payload}) => {
let result;
switch(type) {
case SELECT_CARD:
result = feedback(payload);
break;
default:
result = null;
} return isSameType(State, result) ? result.execWith(prevState): prevState;
} const sillyVerb = createAction('SILLY_VERB'); console.log(
reducer(
state,
selectCard('green-square')
)
)

[Functional Programming ADT] Adapt Redux Actions/Reducers for Use with the State ADT的更多相关文章

  1. [Functional Programming] Randomly Pull an Item from an Array with the State ADT (Pair)

    Functor composition is a powerful concept that arises when we have one Functor nested in another Fun ...

  2. [React + Functional Programming ADT] Connect State ADT Based Redux Actions to a React Application

    With our Redux implementation lousy with State ADT based reducers, it is time to hook it all up to a ...

  3. Beginning Scala study note(4) Functional Programming in Scala

    1. Functional programming treats computation as the evaluation of mathematical and avoids state and ...

  4. [Functional Programming ADT] Combine Multiple State ADT Based Redux Reducers

    Redux provides a convenient helper for combining many reducers called combineReducer, but it focuses ...

  5. [Functional Programming ADT] Create a Redux Store for Use with a State ADT Based Reducer

    With a well defined demarcation point between Redux and our State ADT based model, hooking up to a R ...

  6. [Functional Programming ADT] Create State ADT Based Reducers (applyTo, Maybe)

    The typical Redux Reducer is function that takes in the previous state and an action and uses a swit ...

  7. [Functional Programming ADT] Initialize Redux Application State Using The State ADT

    Not only will we need to give our initial state to a Redux store, we will also need to be able to re ...

  8. [Functional Programming] Combine State Dependent Transactions with the State ADT (composeK to replace multi chian call)

    When developing a Finite State Machine, it is often necessary to apply multiple transitions in tande ...

  9. [Functional Programming] Combine Multiple State ADT Instances with the Same Input (converge(liftA2(constant)))

    When combining multiple State ADT instances that depend on the same input, using chain can become qu ...

随机推荐

  1. 史上最全的web前端系统学习教程!

    这份资料整理花了近7天,如果感觉有用,可以分享给更有需要的人. 在看接下的介绍前,我先说一下整理这份资料的初衷: 我的初衷是想帮助在这个行业发展的朋友和童鞋们,在论坛博客等地方少花些时间找资料,把有限 ...

  2. jquery中的done和always解决ajax问题

    昨天写一个跨域请求json数据的实例.遇到传值问题,尝试了各种方式都不行,后来发现,同一个地址,同一个ip请求次数频繁传值相同的话,ajax会默认跟一个&?时间戳,这就导致我传过去的值是错误的 ...

  3. Intellij IDEA 去掉Mapper文件中的背景

    1.在setting中输入:inspection --> SQL 2.去掉背景颜色,Apply即可

  4. Java篇:IO流

    流(IO) 四个基本流: InputStream(输入字节流).OutputStream(输出字节流).writer(输出字符流).reader(输入字符流)-四个基本流都是抽象类不能实例化,固只能用 ...

  5. Sqlite的导入导出功能

    导出,使用dump命令 导入,使用read命令 可以直接执行,类似 sqlite xxx.db3 ".read ../sss.sql"

  6. 转:nginx+CGI/FASTCGI

    简介版: 1.fastcgi与cgi区别:fastcgi通过线程来响应请求,而cgi对每个请求生成一个进程. 2.典型nginx数据传输过程:user->nginx->本地socket(请 ...

  7. 88. Merge Sorted Array【Easy】【双指针-不用额外空间归并两个有序数组】

    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note: T ...

  8. Bzoj3942 Censoring(KMP)

    \(KMP\)问题的核心在于数组\(next\)(或者\(pre\)/\(fail\),各种叫法),几乎所有的此类型题都是需要计算\(next\)的. 这里解释一波\(next\):即满足字符子串\( ...

  9. phonegap安卓视频播放解决方案

    使用phonegap开发的时候,视频播放很多人一开始选择用html5的Video标签作为备选方案,实际上这种方案在真实环境下常常是无法满足需求的,因为目前HTML5的Video标签只支持MP4,OGG ...

  10. Problem J: 零起点学算法89——程序设计竞赛

    #include<stdio.h> //选择排序法 int main(){ ]; while(scanf("%d",&n)!=EOF){ ;i<n;i++ ...