[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 thinking in State.
First, we need to know the type of State: State returns Pair with Unit on the left, and state on the right:
State(state => Pair(Unit, state))
We don't need to manully add Pari and Unit type, State provides helper methods for doing this, but it is important to understand.
On the left side, Unit is a variable, types can be very depends on your needs.
On the right side, state has to be a fixed type, you better do NOT change it.
To access right side 'state', we can using 'modify' or 'set' helpers.
To access left side 'Unit', we can using 'get' helper.
One benifit by using State, is that we got lazyness for the function, means we can chain different state transition together.
Let's see an example:
const State = require('crocks/State');
const {get, modify} = State;
// add :: Int -> Int -> Int
const add = x => y => y + x;
// if we want to chain state transform, we need to have a function
// addNickel :: () -> State Int ()
//const addNickel = () => State(s => Pair(Unit(), s + 5))
const addNickel = () => modify(add());
// addDime = () -> State Int ()
const addDime = () => modify(add());
const addQuarter = () => modify(add());
In the example, we define three 'addXX' functions, each add different values.
We can compose them together:
// state :: State Int()
const state = addNickel()
.chain(addDime) // Pair( (), 15 )
.chain(addQuarter) // Pair( (), 40 )
.chain(addQuarter) // Pair( (), 65 )
.chain(addQuarter) // Pair( (), 90 )
.chain(addQuarter) // Pair( (), 115 ) console.log(
state
.runWith()
)
It is important to call 'runWIth', 'execWith' or 'evalWith'... because State is lazy, you need to trigger it. We chain multi state together to get new state, or let's saying we are keep modfiying the state. At this point, we didn't touch the 'Unit' part.
Then why 'Unit' / left side part can be useful?
We can think 'Unit' / left side part is the result of 'state' / right side part after mapping to some logic / function.
For example, we want to build a function, only return True of False, if number is greater than 100, return True, otherwise return False:
// canVend :: Int -> Boolean
const canVend = n => n >= ; console.log(
get()
.map(canVend)
.runWith()
) // False console.log(
get()
.map(canVend)
.runWith()
) // True
For calling 'get()', we are targeting left side part, which is 'Unit', it waiting some mapping function, which can transform state and put result into Unit. If we don't provide any mapping function, 'get()' will just copy the value from 'state':
console.log(
get()
.runWith()
) // Pair(10, 10) console.log(
get()
.map(x => x * )
.runWith()
) // Pair(20, 10) // the same as:
console.log(
get(x => x * )
.runWith()
) // Pair(20, 10)
In 'addNickle' example, we want to only get result in Boolean, if the state is greater than 100 or not, we can keep the state transform part untouched, only chain the getter logic in final state.
// canVend :: Int -> Boolean
const canVend = n => n >= ; // evaluate :: () -> State Int Bool
const evaluate = () => get(canVend); // get().map(fn) === get(fn) // state :: State Int()
const state = addNickel()
.chain(addDime) // Pair( (), 15 )
.chain(addQuarter) // Pair( (), 40 )
.chain(addQuarter) // Pair( (), 65 )
.chain(addQuarter) // Pair( (), 90 )
.chain(addQuarter) // Pair( (), 115 ) console.log(
state
.chain(evaluate)// Pair( true, 115 )
.runWith()
)
Full Code:
---
const State = require('crocks/State');
const {get, modify} = State;
// add :: Int -> Int -> Int
const add = x => y => y + x;// if we want to chain state transform, we need to have a function
// addNickel :: () -> State Int ()
//const addNickel = () => State(s => Pair(Unit(), s + 5))
const addNickel = () => modify(add());
// addDime = () -> State Int ()
const addDime = () => modify(add());
const addQuarter = () => modify(add());
// canVend :: Int -> Boolean
const canVend = n => n >= ;
// evaluate :: () -> State Int Bool
const evaluate = () => get(canVend); // get().map(fn) === get(fn)
// state :: State Int()
const state = addNickel()
.chain(addDime) // Pair( (), 15 )
.chain(addQuarter) // Pair( (), 40 )
.chain(addQuarter) // Pair( (), 65 )
.chain(addQuarter) // Pair( (), 90 )
.chain(addQuarter) // Pair( (), 115 )
console.log(
state
.chain(evaluate)// Pair( true, 115 )
.runWith()
)
[Functional Programming] Introduction to State, thinking in State的更多相关文章
- [Functional Programming] Using ComposeK for both get State and modify State
We have State like this: const state = { cards: [ { id: "green-square", color: "green ...
- [Functional Programming + React] Provide a reasonable default value for mapStateToProps in case initial state is undefined
For example we have a component, it needs to call 'react-redux' connect function. import { compose, ...
- [Functional Programming ADT] Initialize Redux Application State Using The State ADT
Not only will we need to give our initial state to a Redux store, we will also need to be able to re ...
- [Functional Programming Monad] Combine Stateful Computations Using A State Monad
The true power of the State ADT really shows when we start combining our discrete, stateful transact ...
- [Functional Programming Moand] Update The State Of A State Monad (put)
Stateful computations require the ability for their state to change overtime. We take a look on one ...
- [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 ...
- [Functional Programming] Transition State based on Existing State using the State ADT (liftState, composeK)
While sometimes outside input can have influence on how a given stateful transaction transitions, th ...
- Beginning Scala study note(4) Functional Programming in Scala
1. Functional programming treats computation as the evaluation of mathematical and avoids state and ...
- Functional programming
In computer science, functional programming is a programming paradigm, a style of building the struc ...
随机推荐
- 爬虫IP被禁的简单解决方法
爬虫以前听上去好厉害好神秘的样子,用好了可以成就像Google.百度这样的索索引擎,用不好可以凭借不恰当的高并发分分钟崩掉一个小型网站.写到这里想到12306每年扛住的并发请求量,觉得好牛逼. 爬虫和 ...
- D3D9 effect (hlsl)(转)
转:http://blog.csdn.net/leonwei/article/details/8212800 effect其实整合了shader和render state的控制两大部分内容 9.1 ...
- linux socket编程示例
#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include &l ...
- Netty之解决TCP粘包拆包(自定义协议)
1.什么是粘包/拆包 一般所谓的TCP粘包是在一次接收数据不能完全地体现一个完整的消息数据.TCP通讯为何存在粘包呢?主要原因是TCP是以流的方式来处理数据,再加上网络上MTU的往往小于在应用处理的消 ...
- 错误:不小心的VS重命名
问题再现 不小心勾选了“在字符串中搜索”.
- 星际之门SG1第一至十季/全集Stargate SG-1迅雷下载
英文译名 Stargate SG-1 (第一至十季) (1997-2008)Syfy.本季看点:<星际之门 SG-1>1997年起在美播出第一季,并于全球30多个国家播映,反应热烈,今年( ...
- 多个so中模板单例的多次实例化
在Android打包项目时,发现登录功能不能使用了,logcat中也没发现什么问题,最后一行一行log定位到了问题.原来是一个so文件中的构造函数被初始化二次! 这个单例是通过继承模板来实现的(暂 ...
- C# Linq获取两个List或数组的差集交集
List<); list1.Add(); list1.Add(); List<); list2.Add(); list2.Add(); //得到的结果是4,5 即减去了相同的元素. L ...
- [Web 前端] 前端频道之团队维护、聚合、订阅
cp from :https://blog.csdn.net/ivan820819/article/details/78885404 国内 腾讯 ISUX 腾讯全端 AlloyTeam 奇舞周刊 阿里 ...
- The Art of Deception
前言 一些黑客毁坏别人的文件甚至整个硬盘,他们被称为电脑狂人(crackers)或计算机破坏者(vandals).另一些新手省去学习技术的麻烦,直接下载黑客工具侵入别人的计算机,这些人被称为脚本小子( ...