• [Functional Programming] Using JS, FP approach with Arrow or State Monad


    Using Naive JS:

    const {modify, get} = require('crocks/State');
    const K = require('crocks/combinators/constant');
    const B = require('crocks/combinators/composeB');
    
    const assign = require('crocks/helpers/assign');
    const prop = require('crocks/Maybe/prop');
    const option = require('crocks/pointfree/option');
    
    // rando : Integer -> State Object Float
    const rando = x => {
        const seed = (1103515245 * x + 12345) & 0x7fffffff
        const value = (seed >>> 16) / 0x7fff;
    
        return modify(assign({seed})) // update the seed Pair(_, seed)
            .map(K(value)); // update the value Pair(value, seed)
    }
    
    // pullRandom :: Integer -> State Object Float
    const pullRandom = defSeed =>
        get(s => pluckSeed(defSeed)).chain(rando);
    
    // pluckSeed :: Integer -> Object -> Integer
    const pluckSeed =
        def => B(option(def), prop('seed'))
    
    module.exports = {
        pullRandom
    };

    The main problem is inside 'rando' function, not really a FP way doing stuff.

    Arrow approach:

    const {modify, get} = require('crocks/State');
    const Arrow = require('crocks/Arrow');
    const K = require('crocks/combinators/constant');
    const B = require('crocks/combinators/composeB');
    
    const assign = require('crocks/helpers/assign');
    const branch = require('crocks/Pair/branch');
    const prop = require('crocks/Maybe/prop');
    const option = require('crocks/pointfree/option');
    const merge = require('crocks/pointfree/merge');
    
    // calcSeed :: Arrow Integer
    const calcSeed = Arrow(x => (1103515245 * x + 12345) & 0x7fffffff);
    
    // value :: Arrow (Pair Integer) -> Pair (Integer Float)
    const value = Arrow(x => (x >>> 16) / 0x7fff).second();
    
    // genRandom :: Arrow Integer Object
    const genRandom = calcSeed
        .map(branch)
        .compose(value)
        .map(p => [p.fst(), p.snd()])
    
    // rando : Integer -> State Object Float
    const rando = x => {
        const [seed, value] = genRandom.runWith(x);
        return modify(assign({seed})) // update the seed Pair(_, seed)
            .map(K(value)); // update the value Pair(value, seed)
    }
    
    // pullRandom :: Integer -> State Object Float
    const pullRandom = defSeed =>
        get(s => pluckSeed(defSeed)).chain(rando);
    
    // pluckSeed :: Integer -> Object -> Integer
    const pluckSeed =
        def => B(option(def), prop('seed'))
    
    module.exports = {
        pullRandom
    };

    It becomes complex with we need to do Pari and Arrow.

    State version:

    const {modify, get} = require('crocks/State');
    const B = require('crocks/combinators/composeB');
    
    const assign = require('crocks/helpers/assign');
    const prop = require('crocks/Maybe/prop');
    const option = require('crocks/pointfree/option');
    
    //initialState :: GameState
    const initialState = {
        deck: [],
        seed: 23
    }
    
    // newSeed :: Int -> INt
    const newSeed = seed => (1103515244 * seed + 12345) & 0x7fffffff;
    // calcValue :: Int -> Float
    const calcValue = seed => (seed >>> 16) / 0x7fff;
    
    // pluckSeed :: Integer -> GameState -> Integer
    const pluckSeed =
        def => B(option(def), prop('seed'));
    
    // getSeed :: () -> State GameState Int
    const getSeed = () => get(pluckSeed({seed: 0})); 
    
    // putSeed :: Int -> State GameState ()
    const putSeed = seed => modify(assign({seed}));
    
    // genSeed :: () -> State GameState ()
    // get default seed
    // map to a new seed
    // update current seed in state
    const genSeed = () => 
        getSeed()
            .map(newSeed)
            .chain(putSeed);
    
    // evaluate :: () -> State GameState Float        
    const evaluate = () => 
        getSeed()
            .map(calcValue);
    
    // pullRandom :: () -> State GameState Float     
    const pullRandom = () => 
        genSeed()
            .chain(evaluate);    
    
    console.log(
        pullRandom()
        .runWith(initialState)
    )

    The idea is easier to follow and thinking in a way of state transition. 

  • 相关阅读:
    python全栈开发day54-mysql库操作、表操作、数据类型、完整性约束
    CentOS7.5安装nodejs 转
    python全栈开发day53-mysql
    python全栈开发day52-bootstrap的运用
    python全栈开发day51-jquery插件、@media媒体查询、移动端单位、Bootstrap框架
    机器学习之交叉验证和网格搜索
    机器学习之混淆矩阵
    机器学习之朴素贝叶斯算法
    机器学习之TF-IDF
    机器学习之K-近邻算法
  • 原文地址:https://www.cnblogs.com/Answer1215/p/10601436.html
Copyright © 2020-2023  润新知