zoukankan      html  css  js  c++  java
  • [Functional Programming] Build a Linear congruential generator

    What we are going to do in this post, is to build a random number generator. As you might know that Javascript provides Math.random(), but the problem for Math.random() is you cannot control it, what we actully want is a number generator which can provide the same sequence of random numbers. Imaging we have a game, everytime we start the game it will genarte 

    [5,7,9,8,1,3....]

    Second times, it runs the game, it produce the same output: [5,7,9,8,1,3....]. This kind of number generator is called: Linear congruential generator 

    We are going to use 'crocks/State' to coding it:

    const log = require('./lib/log');
    
    const State = require('crocks/State');
    const B = require('crocks/combinators/composeB');
    const K = require('crocks/combinators/constant');
    const prop = require('crocks/Maybe/prop');
    const option = require('crocks/pointfree/option');
    const {modify, get} = State;
    const assign = require('crocks/helpers/assign');
    
    // pluckSeed :: Integer -> Object -> Integer
    const pluckSeed =
        def => B(option(def), prop('seed'))
    
    // 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(pluckSeed(defSeed)).chain(rando);
    
    // limitIndx :: Integer -> Float -> Integer
    const limitIndx = len => x => (x * len) | 0;
    
    const seed = 76;
    log(
        State.of(seed)
        .chain(pullRandom) // 'Pair( 0.13864558854945525, { seed: 297746555 } )'
        .map(limitIndx(52)) // 'Pair( 7, { seed: 297746555 } )'
        .runWith({seed: 10})
    );

    Let's explain some operator a little bit:

    const B = require('crocks/combinators/composeB');

    'composeB', the same as 'compose' read from right to left, the only difference is it only accepts two functions! no more no less.

    // pluckSeed :: Integer -> Object -> Integer
    const pluckSeed =
        def => B(option(def), prop('seed'))

    'pluckSeed', we use 'prop' from 'Maybe', to get value from Maybe, we need to use 'option', if Maybe returns Nothing, then we use the default value from 'option(def)'.

    const State = require('crocks/State');
    const {modify, get} = State;
    
    // 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)
    }

    'modify' it a constructor' method for 'State' moand, the State monad is constructed by Pair moand:

    State(Pair(a, s))

    On the left side, 'a' is the new state which come from 's' after mapping to some function. 's' is the origianl state.

    When you call 'modify', it is actually modifying the right side 's':

    modify(assign({seed})) // update the seed Pair(_, seed)

    When you call .map(fn), it is change the value on the left side of Pair:

        return modify(assign({seed})) // update the seed Pair(_, seed)
            .map(constant(value)); // update the value Pair(value, seed)
  • 相关阅读:
    iOS AFNetworking 2.6.0框架导入报错解决方法
    GitHub 上都有哪些值得关注学习的 iOS 开源项目?
    iOS开发ARC机制下的内存管理技术要点
    UIColor延伸:判断两个颜色是否相等
    iOS中的单例模式
    明天再整理,睡觉!
    pushViewController:animated:的问题
    解决UINavigationController在pushViewController时出现的"卡顿"问题
    在某OC字符串中,搜索指定的某字符串:-rangeOfString:
    SSH整合redis和MongoDB错误笔记
  • 原文地址:https://www.cnblogs.com/Answer1215/p/10544101.html
Copyright © 2011-2022 走看看