[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 ...
随机推荐
- AVR Programming Methods
AVR Programming Methods There are many ways to program AVR microcontrollers. Since many people ask ...
- ASP.NET MVC中实现属性和属性值的组合,即笛卡尔乘积02, 在界面实现
在"ASP.NET MVC中实现属性和属性值的组合,即笛卡尔乘积01, 在控制台实现"中,在控制台应用程序中实现了属性值的笛卡尔乘积.本篇在界面中实现.需要实现的大致如下: 在界面 ...
- Spring Boot 2.0 + zipkin 分布式跟踪系统快速入门
原文:https://www.jianshu.com/p/9bfe103418e2 注意 Spring Boot 2.0之后,使用EnableZipkinServer创建自定义的zipkin服务器已经 ...
- mycat应用场景
mycat应用场景 以下是几个典型的应用场景:单纯的读写分离,此时配置最为简单,支持读写分离,主从切换分表分库,对于超过1000万的表进行分片,最大支持1000亿的单表分片多租户应用,每个应用一个库, ...
- Nginx rewrite URL examples with and without redirect address
原文地址: http://www.claudiokuenzler.com/blog/436/nginx-rewrite-url-examples-with-without-redirect-addre ...
- C#编程(五十八)----------并行集合
并行集合 对于并行任务,与其相关紧密的就是对一些共享资源,数据结构的并行访问.经常要做的就是对一些队列进行加锁-解锁,然后执行类似插入,删除等等互斥操作. .NET4提供了一些封装好的支持并行操作数据 ...
- iReport使用方法
新建报表,依次单击“文件/New…”,弹出窗口 选择”Blank A4”,单击”Open this Template” 依次单击“下一步/完成”,得到一个新的report 单击”OK”按钮完成数据集设 ...
- WordPress基础:get_page_link获取页面地址
函数:get_page_link(页面id编号) 作用:获取指定页面的链接地址 用法: $link = get_page_link(2); 输出为:xxx/?page_id=2 如在循环里则不用填写i ...
- 分布式系统:CAP
一致不太理解CAP,最近好像有点感觉了,这里写下来,先介绍下CAP的定义: C:一致性.写完数据后,立马能看到最新数据. A:可用性.所有请求必须有响应. P:分区容错性.网络或服务器故障不会导致系统 ...
- ASP.NET MVC:mvc pattern
There are three pieces to the MVC pattern: The model—The domain that your software is built around. ...