[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 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)))的更多相关文章
- [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 ...
 
随机推荐
- 使用MXNet远程编写卷积神经网络用于多标签分类
			
最近试试深度学习能做点什么事情.MXNet是一个与Tensorflow类似的开源深度学习框架,在GPU显存利用率上效率高,比起Tensorflow显著节约显存,并且天生支持分布式深度学习,单机多卡.多 ...
 - 可参考的js代码
			
function addcompanyFinalBalance(){ var currentDate = new Date(); var currentYear = date.getFullYear( ...
 - hdu 1422(贪心)
			
重温世界杯 Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Total Submiss ...
 - Delphi读写二进制文件
			
http://www.cnblogs.com/hnxxcxg/p/3691742.html 二进制文件(也叫类型文件),二进制文件是由一批同一类型的数据组成的一个数据序列,就是说一个具体的二进制文件只 ...
 - AC日记——绿豆蛙的归宿 codevs 2488
			
绿豆蛙的归宿 思路: topsort+期望dp: 代码: #include <cstdio> #include <cstring> #include <iostream& ...
 - ASP.NET MVC中DropDownList的使用
			
Asp.net MVC中的DropDownLists貌似会让一开始从Asp.net Forms转过来的程序员造成不少迷惑.这篇文章讲述了为了使用DropDownLists,你需要在Asp.Net MV ...
 - HDU 6351.Beautiful Now-暴力、全排列、思维 (2018 Multi-University Training Contest 5 1002)
			
2018 Multi-University Training Contest 5 6351.Beautiful Now 题意就是交换任意两个数字,问你交换k次之后的最小值和最大值. 官方题解: 哇塞, ...
 - 初始github——git的简单使用
			
初学者~ 有两篇吧,一篇在github上 https://github.com/DefaultYuan/Git-Pro/wiki/Introduction 文章来源:<git的简单使用> ...
 - IBM-Club IntelliJ IDEA 开发环境的安装
			
各位小伙伴初次使用IDE,可能还是有许多疑惑,因此这篇博客阿鲁给大家分享一下,自己平时是如何安装IntelliJ IDEA的 1.原料:安装包,直接百度搜索进入官网下载 记住是Ultimate版本呦, ...
 - POJ1325Machine Schedule(匈牙利算法)
			
Machine Schedule Time Limit: 1000MS Memory L ...