[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 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 Promises
graced 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)))的更多相关文章
- [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] 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 ...
- [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] Define Discrete State Transitions using the State ADT
We build our first state transactions as two discrete transactions, each working on a specific porti ...
- [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 ...
- [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 ...
- [Functional Programming] Reader with Async ADT
ReaderT is a Monad Transformer that wraps a given Monad with a Reader. This allows the interface of ...
- [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] 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 ...
随机推荐
- dubbo消费方超时处理
在我们分布式系统中,远程调用可能随时会出现调用超时,然后抛异常 在dubbo内部,默认设置的是500ms(好像是),所以,对于crud事物大的系统来讲肯定是要自定义超时时间咯,作为消费方,自然是优先级 ...
- Android之Activity
Activity总结: Activity的顶层View是DecorView,而我们在onCreate函数中通过setContentView设置的View只不过是这个DecorView的一部分罢了.De ...
- 怎么在32位windows系统上搭建爬虫框架scrapy?
禁止转载: 自学python,然后搭建爬虫框架scrapy.费了我一上午的心血.终于搭建成功,以防以后忘记搭建流程,特此撰写此贴,开写 ******************************** ...
- sybase ase 重启
sybase ase 重启 https://blog.csdn.net/davidmeng10/article/details/50344305 https://blog.csdn.net/wengy ...
- 最快的序列化组件protobuf的.net版本protobuf.net
Protobuf是google开源的一个项目,用户数据序列化反序列化,google声称google的数据通信都是用该序列化方法.它比xml格式要少的多,甚至比二进制数据格式也小的多. Prot ...
- java异常基本知识
Throwable |--Error |--Exception |--RuntimeException 异常体系的特点:异常体系中的所有类 ...
- flutter演示项目:游侠客户端
使用flutter实现的游侠客户端. 还有一些页面没写,最主要的问题是无法解析html富文本. https://github.com/axel10/flutter_ali213_client_demo
- Nodejs微信与Bot framework通过Direct Line连接
背景 最近开发了一个Bot Framework的小工具,能够通过Luis分析出用户输入的文本,对文本中的StyleNo/FabricNo/TrimNo提取出来,并传入另一个小系统进行查询出结果,包括文 ...
- 计蒜客 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 ...
- sqlmap的小试牛刀
这次算是一次用sqlmap的例子,写的很水. 目的:通过工具扫描到了后台的数据库的地址(如下图),想通过sqlmap找到数据库的用户和密码进入到数据库(首先可以尝试一下root:root一般都是这个情 ...