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. XGBOOST/GBDT,RandomForest/Bagging的比较

    原创文章:http://blog.csdn.net/qccc_dm/article/details/63684453 首先XGBOOST,GBDT,RF都是集成算法,RF是Bagging的变体,与Ba ...

  2. python 多进程multiprocessing 模块

    multiprocessing 常用方法: cpu_count():统计cpu核数 multiprocessing.cpu_count() active_children() 获取所有子进程 mult ...

  3. CentOS6.x 安装升级Python2.7.x Python3.4.x

    CentOS6.x 安装升级Python2.7.x Python3.4.x 2015-06-07• CentOS.Linux • 评论关闭 CentOS release 6.6 (Final) 安装升 ...

  4. Photoshop CC 2015

    1.Ctrl 加 + -号实现放大缩小2.Ctrl+T 自由变换3.Ctrl+D 取消选区,再选择处理完后想要选中别的区域的话要取消之前选中的区域,要不然之前的区域一直都是选中状态4.F12 将文件恢 ...

  5. Python 进阶 之 traceback模块

    Traceback模块官方英文描述: Help on module traceback: NAME traceback - Extract, format and print information ...

  6. Laravel开启跨域的方法

    1.建立中间件Cors.php 命令:php artisan make:middleware Cors 在/app/Http/Middleware/ 目录下会出现一个Cors.php 文件. 内容如下 ...

  7. java Socket启动服务

    java -cp /Library/WebServer/Documents/Java/test/src com.zhidian.soft.sendOfClick localhost 8888 java ...

  8. .NET Core Runtime ARM32 builds now available

    原文地址:传送门 .NET Core Runtime ARM32 builds now available The .NET Core team is now producing ARM32 buil ...

  9. 使用moneykey对APP进行健壮性测试

    注意:moneykey对app按钮伪随机点击,只能测试app稳定性和健壮性,无法进行常规测试 1.安装 A.jdk(不详细介绍) B.安装配置android配置环境:Android Studio 此环 ...

  10. 【wordpress】 $wpdb 应用实例

    <?php require_once('e:/php/wordpress/wp-blog-header.php');//注释掉这一句就出错了 global $wpdb; $a = $wpdb-& ...