[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 ...
 
随机推荐
- STM32F4 Timer External Clock TI2 Both Edges Demo
			
#define CLK_FREQ ( 10000 ) #define CORE_FREQ ( 168000000 ) static void TIM_GPIO_Config( void ) { GPI ...
 - jquery智能弹出层,自己主动推断位置
			
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
 - Complete uninstall on Mac, HELP!
			
Remove these directories: /Applications/Xamarin Studio.app /Developer/MonoTouch /Developer/MonoAndro ...
 - AngularJS路由系列(3)-- UI-Router初体验
			
本系列探寻AngularJS的路由机制,在WebStorm下开发. AngularJS路由系列包括: 1.AngularJS路由系列(1)--基本路由配置2.AngularJS路由系列(2)--刷新. ...
 - Odoo进销存(采购、销售、仓库)入门教程 - 下
			
转帖地址:http://blog.csdn.net/wangnan537/article/details/46475105 2. 进销存实务 2.1 销售产品 李逍遥接到客户苏州美尚邻里超市购买10只 ...
 - 利用MPMoviePlayerViewController 播放视频 iOS
			
方法一: @property (nonatomic, strong) MPMoviePlayerController *player; NSString *url = [[NSBundle mainB ...
 - adb install -r 中出现INSTALL_FAILED_UNKNOWN_SOURCES,怎样解决?
			
adb install -r 中出现INSTALL_FAILED_UNKNOWN_SOURCES,怎样解决? D:\android_code\0708\tools>adb install -r ...
 - how to use kvo with swift (怎样在swift中使用kvo)
 - 初学者必读:IBM长文解读人工智能、机器学习和认知计算
			
转自:https://zhuanlan.zhihu.com/p/27228015?utm_source=weibo&utm_medium=social 人工智能的发展曾经经历过几次起起伏伏,近 ...
 - HikariCP 脑火Failed to obtain JDBC Connection: You need to run the CLI build and you need target/classes in your classpath to run.
			
测试了一下 HikariCP 连接池报错,无解 十一月 16, 2017 5:31:59 下午 org.apache.catalina.core.StandardContext loadOnStart ...