[Functional Programming ADT] Adapt Redux Actions/Reducers for Use with the State ADT
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的更多相关文章
- [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 ...
- [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 ...
- Beginning Scala study note(4) Functional Programming in Scala
1. Functional programming treats computation as the evaluation of mathematical and avoids state and ...
- [Functional Programming ADT] Combine Multiple State ADT Based Redux Reducers
Redux provides a convenient helper for combining many reducers called combineReducer, but it focuses ...
- [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 ...
- [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 ...
- [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 ...
- [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 ...
- [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 ...
随机推荐
- Docker for Windows 里的Shared Drives 设置不生效
原文地址:传送门 问题描述:Docker中的settings里的Shared Drives 选择对应盘符后,点击Apply后无法生效,没办法选择对应盘符进行分享. 解决办法:win+R ,键入gped ...
- VS Code开发技巧集锦
2016 年 9 月 23-24 日,由 CSDN 和创新工场联合主办的“MDCC 2016 移动开发者大会? 中国”(Mobile Developer Conference China)将在北京? ...
- Bootstrap 实现CRUD示例及代码
https://github.com/wenzhixin/bootstrap-table-examples/blob/master/crud/index.html <!DOCTYPE html& ...
- Win7 + VirtualBox + CentOS(无桌面), 扩容
http://www.2cto.com/os/201401/269730.html 对于目前的网络开发者来说,比较好的搭档就是Win7+VirtualBox+CentOS的组合,既可以发挥Linux强 ...
- 循序渐进PYTHON3(十三) --2-- DJANGO之FORM表单(自动生成HTML标签和自定制提示信息)
在上一次的代码上做出进一步修改,使之能在页面上显示自定制的报错信息,并且使用form自动创建标签的功能. views.py from django.shortcuts import render,Ht ...
- AutoHotKey 常用脚本
; IMPORTANT INFO ABOUT GETTING STARTED: Lines that start with a ; semicolon, such as this one, are c ...
- 设计模式-模板方法模式(the Template Method Pattern)
本文由@呆代待殆原创,转载请注明出处:http://www.cnblogs.com/coffeeSS/ 模板方法模式简介 这是一个被用的相当广泛的一种设计模式,变体也特别多,他建立一个抽象类定义一个算 ...
- php elasticsearch 关键词搜索配置
CURL接口方式调用数据,网络搜索了一下大都不能使用,自己研究了一下. 参数格式按照如下传递: PHP: 'query' => [ "bool" => [ " ...
- 2016.4.3NOI上较难的动规题目(仔细分析样例)--王老师讲课整理
1.NOI 191:钉子和小球 总时间限制: 1000ms 内存限制: 65536kB 描述 有一个三角形木板,竖直立放,上面钉着n(n+1)/2颗钉子,还有(n+1)个格子(当n=5时如图1).每 ...
- Mac下JAVA开发环境搭建
最近开始学习JAVA, 首先配置下环境! 1.Mac自带的jdk版本老了,需要到oracle官网去下载新的jdk,具体下载那个版本看个人需求,然后安装. 安装完成之后打开Terminal, 执行命 ...