When combining multiple State ADT instances that depend on the same input, using chain can become quite burdensome. We end up having to play leapfrog with values inside of nested chain statements. Very reminiscent of the old callback nastiness we had to deal with before Promisesgraced our existence.

But fear not, but taking advantage of the Applicative Functor portion of the State ADT in combination with the converge combinator, we can apply these types of transitions in unison, passing the value to both virtually simultaneously.

For example:

// () -> b
const validateAnswer = converge(
liftA2(equals),
cardToHint,
getHint
)

'validateAnswer' return a boolean value.

We want to take this value, and pass to two functions 'setIsCorrect' & 'updateRank'

// b -> ()
const setIsCorrect = b => over('isCorrect', constant(b)); // b -> ()
const updateRank = b => over('rank', adjustRank(b));

One functional way to do this is using 'converge':

const applyFeedback = converge(
liftA2(constant),
setIsCorrect,
updateRank
)

----------------

const {prop, 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:
} const inc = x => x + ;
const dec = x => x - ;
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(, );
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
)
// () -> b
const validateAnswer = converge(
liftA2(equals),
cardToHint,
getHint
)
// b -> ()
const setIsCorrect = b => over('isCorrect', constant(b)); const adjustRank = compose(limitRank, incOrDec);
// b -> ()
const updateRank = b => over('rank', adjustRank(b)); const applyFeedback = converge(
liftA2(constant),
setIsCorrect,
updateRank
) const feedback = composeK(
applyFeedback,
validateAnswer
) console.log(
feedback('green-square')
.execWith(state)
)

[Functional Programming] Combine Multiple State ADT Instances with the Same Input (converge(liftA2(constant)))的更多相关文章

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

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

  2. [Functional Programming] Compose Simple State ADT Transitions into One Complex Transaction

    State is a lazy datatype and as such we can combine many simple transitions into one very complex on ...

  3. [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 ...

  4. [Functional Programming] Define Discrete State Transitions using the State ADT

    We build our first state transactions as two discrete transactions, each working on a specific porti ...

  5. [Functional Programming Monad] Substitute State Using Functions With A State Monad (get, evalWith)

    We take a closer look at the get construction helper and see how we can use it to lift a function th ...

  6. [Functional Programming] Introduction to State, thinking in State

    Recently, I am learning Working with ADT. Got some extra thought about State Monad. Basiclly how to ...

  7. [Functional Programming] Reader with Async ADT

    ReaderT is a Monad Transformer that wraps a given Monad with a Reader. This allows the interface of ...

  8. [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 ...

  9. [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 ne ...

随机推荐

  1. bp神经网络模型推导与c语言实现(转载)

    转载出处:http://www.cnblogs.com/jzhlin/archive/2012/07/28/bp.html BP 神经网络中的 BP 为 Back  Propagation 的简写,最 ...

  2. 带你入门代理模式/SpringAop的运行机制

    SpringAop 是spring框架中最重要的一项功能之一,同时也是企业级开发记录事物日志等不可或缺的一部分,如果说你的系统需要记录用户访问接口的操作,那SpringAop是很完美的了,当然,拦截器 ...

  3. mpvue-小程序之蹲坑记

    1. 不支持 v-html 小程序里所有的 BOM/DOM 都不能用,也就是说 v-html 指令不能用 部分复杂的 JavaScript 渲染表达式 {{}} 双花括号的部分,直接编码到 wxml ...

  4. 离线安装docker最新版,记得要以下三个包。

    如果安装了以前版本,还要删除以下这个包. container-selinux.noarch 2:2.10-2.el7 ============== 离线安装三个rpm -rw-r--r--. 1 ro ...

  5. .net开发CAD2008无法调试的解决方法

    把acad.exe.config文件修改为:------------------------------------------------------------------------------ ...

  6. 计蒜客 30999.Sum-筛无平方因数的数 (ACM-ICPC 2018 南京赛区网络预赛 J)

    J. Sum 26.87% 1000ms 512000K   A square-free integer is an integer which is indivisible by any squar ...

  7. POJ1679 The Unique MST(Kruskal)(最小生成树的唯一性)

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 27141   Accepted: 9712 D ...

  8. RobotFramework操作浏览器滚动条

    RobotFramework操作浏览器滚动条 (2016-12-21 11:52:43) 转载▼ 标签: selenium it 分类: 自动化测试 其实只要是用多了selenium+webdrive ...

  9. 【树状数组】【枚举约数】 - Ambitious Experiment

    给定一个序列,支持以下操作: 对区间[l,r]的每个i,将1i,2i,3i,...这些位置的数都加d. 询问某个位置的数的值. 如果把修改看作对区间[l,r]的每个数+d,那么询问x位置上的数时,显然 ...

  10. 【最小瓶颈生成树】【最小生成树】【kruscal】bzoj1083 [SCOI2005]繁忙的都市

    本意是求最小瓶颈生成树,但是我们可以证明:最小生成树也是最小瓶颈生成树(其实我不会).数据范围很小,暴力kruscal即可. #include<cstdio> #include<al ...