[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 ...
随机推荐
- Java 线程第三版 第四章 Thread Notification 读书笔记
一.等待与通知 public final void wait() throws InterruptedException 等待条件的发生. public final void wait(lo ...
- 调试工具BTrace 的使用--例子
http://www.cnblogs.com/serendipity/archive/2012/05/14/2499840.html
- jQuery $('div>ul') $('div ul'
$('div>ul')是<div>的直接后代里找<ul>: 而$('div ul')是在<div>的所有后代里找<ul>.
- Java嵌入式数据库H2学习总结(一)——H2数据库入门
一.H2数据库介绍 常用的开源数据库有:H2,Derby,HSQLDB,MySQL,PostgreSQL.其中H2和HSQLDB类似,十分适合作为嵌入式数据库使用,而其它的数据库大部分都需要安装独立的 ...
- YUI-compressor 在Linux下安装和使用
介绍一个非常流行的javascript压缩工具YUI compressor,可以提供更好的压缩效率:该工具由著名的Yahoo Exceptional Performance项目组出品. JSMin非常 ...
- JS 日期实用方法
var DateUtil = function(){ /** * 判断闰年 * @param date Date日期对象 * @return boolean true 或false */ this.i ...
- WordPress主题开发:实现分页功能
注意的是这个受后台这里的文章篇数设置所影响~ 一.使用内置方法 (WordPress 4.1以前无效) the_posts_pagination 输出分页式导航,用法: <?php the_po ...
- 吸血鬼日记第一季/全集The Vampire Diaries迅雷下载
本季The Vampire Diaries 1 第一季(2009)看点: <吸血鬼日记>由美国女作家L.J.史密斯的同名畅销系列小说改编而成.4个月前一场可怕的车祸夺去了他们双亲的生命,但 ...
- 迷失第一季/全集Lost 1迅雷下载
迷失 第一季 Lost Season 1 (2004)本季看点:影片主要讲述一架客机坠落在太平洋的孤岛上,48名乘客侥幸生还.面对这种荒芜人烟的小岛,他们如何才能生存下去呢?生还者形形色色,国籍.人种 ...
- ifram 取父窗体的URL地址
var url=''; try { url = window.top.document.referrer ; } catch(M) { if (window.parent) ...