[Functional Programming] Draw Items from One JavaScript Array to Another using a Pair ADT
We want to be able to pick nine random cards from an array of twelve cards, but can run into problems of keeping both the cards already draw and the cards left to draw from. Tracking two bits of state like this can create some hard to maintain argument gymnastics when creating our functions. Luckily we have a datatype Pair
at our disposal that allows us to combine two values in to one value.
We will use this Pair
type to model both a draw pile and a remaining pile, and take advantage of a couple special properties of Pair
that will allow us to combine two Pair
instances in a meaningful way by chain
ing. Just like we have done time and time again with the State
ADT.
We have generated array of cards:
[
{ id: 'orange-square', color: 'orange', shape: 'square' },
{ id: 'orange-triangle', color: 'orange', shape: 'triangle' },
{ id: 'orange-circle', color: 'orange', shape: 'circle' },
{ id: 'green-square', color: 'green', shape: 'square' },
{ id: 'green-triangle', color: 'green', shape: 'triangle' },
{ id: 'green-circle', color: 'green', shape: 'circle' },
{ id: 'blue-square', color: 'blue', shape: 'square' },
{ id: 'blue-triangle', color: 'blue', shape: 'triangle' },
{ id: 'blue-circle', color: 'blue', shape: 'circle' },
{ id: 'yellow-square', color: 'yellow', shape: 'square' },
{ id: 'yellow-triangle', color: 'yellow', shape: 'triangle' },
{ id: 'yellow-circle', color: 'yellow', shape: 'circle' } ]
By the following code:
const {prop,assoc, pick, State, identity, omit, curry, filter, fanout, converge,map, composeK, liftA2, equals, constant,option, chain, mapProps, find, propEq, isNumber, compose, safe} = require('crocks');
const {get, modify, of} = State; // #region generateCards
const state = {
colors: [ 'orange', 'green', 'blue', 'yellow' ],
shapes: [ 'square', 'triangle', 'circle' ]
}; const getState = key => get(prop(key))
const getColors = () => getState('colors').map(option([]))
const getShapes = () => getState('shapes').map(option([]))
const buildCard = curry((color, shape) => ({
id: `${color}-${shape}`,
color,
shape
}));
const buildCards = liftA2(buildCard)
const generateCards = converge(
liftA2(buildCards),
getColors,
getShapes
)
// #endregion
Now what we want to do is split cards array into a Pair,
on the left side pair is the selected card array,
on the rigth side pair is the unselected cards array.
// Splite Cards into two pars
//[Selected Cards] - [UnSelected Cards] const getAt = index => array => array[index];
const unsetAt = index => array => ([...array.slice(, index), ...array.slice(index + )]);
// Deck :: Pair [Card] [Card]
// drawCardAt :: Integer -> [Card] -> Deck
const drawCardAt = index => fanout(
getAt(index),
unsetAt(index)
) console.log(
generateCards()
.map(drawCardAt())
.evalWith(state).fst()
) // { id: 'orange-square', color: 'orange', shape: 'square' } console.log(
generateCards()
.map(drawCardAt())
.evalWith(state).snd() )
/**
[ { id: 'orange-triangle', color: 'orange', shape: 'triangle' },
{ id: 'orange-circle', color: 'orange', shape: 'circle' },
{ id: 'green-square', color: 'green', shape: 'square' },
{ id: 'green-triangle', color: 'green', shape: 'triangle' },
{ id: 'green-circle', color: 'green', shape: 'circle' },
{ id: 'blue-square', color: 'blue', shape: 'square' },
{ id: 'blue-triangle', color: 'blue', shape: 'triangle' },
{ id: 'blue-circle', color: 'blue', shape: 'circle' },
{ id: 'yellow-square', color: 'yellow', shape: 'square' },
{ id: 'yellow-triangle', color: 'yellow', shape: 'triangle' },
{ id: 'yellow-circle', color: 'yellow', shape: 'circle' } ]
*/
Here we use 'fanout' to generate a Pair.
Notice that the left side pair is an object, not an array, we need to use 'bimap' to lift left side pair into Array. To do that,. we use 'bimap'
const drawCardAt = index => compose(
bimap(Array.of, identity),
fanout(
getAt(index),
unsetAt(index)
)
) console.log(
generateCards()
.map(drawCardAt())
.evalWith(state).fst()
) // [{ id: 'orange-square', color: 'orange', shape: 'square' }]
---
const {prop,assoc, pick, bimap, State, identity, omit, curry, filter, fanout, converge,map, composeK, liftA2, equals, constant,option, chain, mapProps, find, propEq, isNumber, compose, safe} = require('crocks');
const {get, modify, of} = State; // #region generateCards
const state = {
colors: [ 'orange', 'green', 'blue', 'yellow' ],
shapes: [ 'square', 'triangle', 'circle' ]
}; const getState = key => get(prop(key))
const getColors = () => getState('colors').map(option([]))
const getShapes = () => getState('shapes').map(option([]))
const buildCard = curry((color, shape) => ({
id: `${color}-${shape}`,
color,
shape
}));
const buildCards = liftA2(buildCard)
const generateCards = converge(
liftA2(buildCards),
getColors,
getShapes
)
// #endregion // Splite Cards into two pars
//[Selected Cards] - [UnSelected Cards] const getAt = index => array => array[index];
const unsetAt = index => array => ([...array.slice(, index), ...array.slice(index + )]);
// Deck :: Pair [Card] [Card]
// drawCardAt :: Integer -> [Card] -> Deck
const drawCardAt = index => compose(
bimap(Array.of, identity),
fanout(
getAt(index),
unsetAt(index)
)
) console.log(
generateCards()
.map(drawCardAt())
.map(chain(drawCardAt()))
.map(chain(drawCardAt()))
.map(chain(drawCardAt()))
.evalWith(state).fst()
) /**
[ { id: 'orange-square', color: 'orange', shape: 'square' },
{ id: 'green-square', color: 'green', shape: 'square' },
{ id: 'green-circle', color: 'green', shape: 'circle' },
{ id: 'blue-triangle', color: 'blue', shape: 'triangle' } ]
*/ console.log(
generateCards()
.map(drawCardAt())
.map(chain(drawCardAt()))
.map(chain(drawCardAt()))
.map(chain(drawCardAt()))
.evalWith(state).snd() )
/**
[ { id: 'orange-triangle', color: 'orange', shape: 'triangle' },
{ id: 'orange-circle', color: 'orange', shape: 'circle' },
{ id: 'green-triangle', color: 'green', shape: 'triangle' },
{ id: 'blue-square', color: 'blue', shape: 'square' },
{ id: 'blue-circle', color: 'blue', shape: 'circle' },
{ id: 'yellow-square', color: 'yellow', shape: 'square' },
{ id: 'yellow-triangle', color: 'yellow', shape: 'triangle' },
{ id: 'yellow-circle', color: 'yellow', shape: 'circle' } ]
*/
[Functional Programming] Draw Items from One JavaScript Array to Another using a Pair ADT的更多相关文章
- a primary example for Functional programming in javascript
background In pursuit of a real-world application, let’s say we need an e-commerce web applicationfo ...
- JavaScript Functional Programming
JavaScript Functional Programming JavaScript 函数式编程 anonymous function https://en.wikipedia.org/wiki/ ...
- [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 ...
- BETTER SUPPORT FOR FUNCTIONAL PROGRAMMING IN ANGULAR 2
In this blog post I will talk about the changes coming in Angular 2 that will improve its support fo ...
- Functional Programming without Lambda - Part 1 Functional Composition
Functions in Java Prior to the introduction of Lambda Expressions feature in version 8, Java had lon ...
- [Javascript ] Array methods in depth - sort
Sort can automatically arrange items in an array. In this lesson we look at the basics including how ...
- Sth about 函数式编程(Functional Programming)
今天开会提到了函数式编程,针对不同类型的百年城方式,查阅了一部分资料,展示如下: 编程语言一直到近代,从汇编到C到Java,都是站在计算机的角度,考虑CPU的运行模式和运行效率,以求通过设计一个高效的 ...
- JavaScript Array methods performance compare
JavaScript Array methods performance compare JavaScript数组方法的性能对比 env $ node -v # v12.18.0 push vs un ...
- Beginning Scala study note(4) Functional Programming in Scala
1. Functional programming treats computation as the evaluation of mathematical and avoids state and ...
随机推荐
- 【POI2017||bzoj4726】Sabota?
上学期putsnan过了一次,这学期认真写了一遍…… #include<bits/stdc++.h> #define N 500010 using namespace std; ]; ,n ...
- linux环境下的GUN make学习笔记(一)
第一章:概述 1.1:make概述 在linux环境下使用make工具能够比较容易的构建一个属于自己的工程,整个工程的编译只需要一个命令就可以完成编译.连接以至于最后的执行.不过我们需要投入一些时间去 ...
- PhpStorm最新版 2017激活办法
特别注意:为避免phpstorm联网时注册失效,请将“0.0.0.0 account.jetbrains.com”添加到hosts文件中. 最新版PhpStorm 2017正式版改进了PHP 7支持, ...
- 使用Rancher管理Docker
使用命令: sudo docker run -it -d --restart=always -p : --name docker-rancher rancher/server 为了更快速的下载应用,推 ...
- 拓扑排序(Topological Order)UVa10305 Ordering Tasks
2016/5/19 17:39:07 拓扑排序,是对有向无环图(Directed Acylic Graph , DAG )进行的一种操作,这种操作是将DAG中的所有顶点排成一个线性序列,使得图中的任意 ...
- COW
COW 时间限制: 1 Sec 内存限制: 64 MB提交: 41 解决: 18[提交][状态][讨论版] 题目描述 Bessie the cow has stumbled across an i ...
- RPD Volume 172 Issue 1-3 December 2016 评论04 end
这一篇作为本期的结束是因为发现后面的一些基本上也是EPR有关的会议内容, Contribution of Harold M. Swartz to In VivoEPR and EPR Dosimetr ...
- Jackson错误:Can not deserialize instance of java.lang.String out of START_OBJECT token
org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not des ...
- pytimechart使用
参考网站:http://pythonhosted.org/pytimechart/userguide.html 安装: sudo apt-get install python-chaco python ...
- ios View之间的切换 屏幕旋转
6.3 View之间的切换 在上面的练习中我们通过移动组件的位置和调整组件的大小来处理横向与纵向的界面布局.但是在界面中有很多组件的时候,对每个组件都进行这样的操作确实是一个麻烦的事情.下面我们看看 ...