zoukankan      html  css  js  c++  java
  • [Functional Programming ADT] Adapt Redux Actions/Reducers for Use with the State ADT

    By using the State ADT to define how our application state transitions over time, we clear up the need for a some of the boilerplate that we typically need for a solid Redux integration. We can keep our action names and creators in the same file as the reducer they are used in, as we no longer need to have separate files to hand the same action across different portions of our state.

    We will build our a single reducer that will handle the integration with Redux and organize our State ADT based reducers in their own files and bring them into our main reducer to handle running our state transitions and the cases where we do not have an transition for a given action.

    // Action a :: {type: string, payload: a}
    // createAction :: String -> a -> Action a
    const createAction = type => payload => ({type, payload});
    const SELECT_CARD = 'SELECT_CARD';
    const selectCard = createAction(SELECT_CARD);
    
    
    // reducer :: (State, a) -> (State AppState ()) | Null
    const reducer = (prevState, {type, payload}) => {
        let result;
        switch(type) {
            case SELECT_CARD:
                result = feedback(payload);
                break;
            default: 
                result = null;   
        }
    
        return isSameType(State, result) ? result.execWith(prevState): prevState;
    }
    
    const sillyVerb = createAction('SILLY_VERB');
    
    console.log(
        reducer(
            state,
            selectCard('green-square')
        )
    )

    If we pass the right action, it will return the result, if a bad action, it keep the prev state untouched.

    ---

    const {prop, isSameType, State, omit, curry, converge,map, composeK, liftA2, equals, constant,option, chain, mapProps, find, propEq, isNumber, compose, safe} = require('crocks');
    const  {get, modify, of} = State; 
    
    const state = {
        cards: [
            {id: 'green-square', color: 'green', shape: 'square'},
            {id: 'orange-square', color: 'orange', shape: 'square'},
            {id: 'blue-triangle', color: 'blue', shape: 'triangle'}
        ],
        hint: {
            color: 'green',
            shape: 'square'
        },
        isCorrect: null,
        rank: 2
    }
    const inc = x => x + 1;
    const dec = x => x - 1;
    const incOrDec = b => b ? dec :  inc;
    const clamp = (min, max) => x => Math.min(Math.max(min, x), max);
    const clampAfter = curry((min, max, fn) => compose(clamp(min, max), fn))
    const limitRank = clampAfter(0, 4);
    const over = (key, fn) => modify(mapProps({[key]: fn}))
    const getState = key => get(prop(key));
    const liftState = fn => compose(
        of,
        fn
    )
    const getCard = id => getState('cards')
        .map(chain(find(propEq('id', id))))
        .map(option({}))
    const getHint = () => getState('hint')
        .map(option({}))
    const cardToHint = composeK(
        liftState(omit(['id'])),
        getCard
    )
    const validateAnswer = converge(
        liftA2(equals),
        cardToHint,
        getHint
    )
    const setIsCorrect = b => over('isCorrect', constant(b));
    const adjustRank = compose(limitRank, incOrDec);
    const updateRank = b => over('rank', adjustRank(b));
    const applyFeedback = converge(
        liftA2(constant),
        setIsCorrect,
        updateRank
    )
    const feedback = composeK(
        applyFeedback,
        validateAnswer
    )
    
    // Action a :: {type: string, payload: a}
    // createAction :: String -> a -> Action a
    const createAction = type => payload => ({type, payload});
    const SELECT_CARD = 'SELECT_CARD';
    const selectCard = createAction(SELECT_CARD);
    
    
    // reducer :: (State, a) -> (State AppState ()) | Null
    const reducer = (prevState, {type, payload}) => {
        let result;
        switch(type) {
            case SELECT_CARD:
                result = feedback(payload);
                break;
            default: 
                result = null;   
        }
    
        return isSameType(State, result) ? result.execWith(prevState): prevState;
    }
    
    const sillyVerb = createAction('SILLY_VERB');
    
    console.log(
        reducer(
            state,
            selectCard('green-square')
        )
    )
  • 相关阅读:
    pip 安装指定版本
    译文:A Robust and Modular Multi-Sensor Fusion ApproachApplied to MAV Navigation
    泡泡一分钟:Perception-aware Receding Horizon Navigation for MAVs
    泡泡一分钟: A Linear Least Square Initialization Method for 3D Pose Graph Optimization Problem
    泡泡一分钟:LandmarkBoost: Efficient Visual Context Classifiers for Robust Localization
    泡泡一分钟:Visual Odometry Using a Homography Formulation with Decoupled Rotation and Translation Estimation Using Minimal Solutions
    小程序在同一行
    oracle分页查询原理浅析
    css实现圆形头像
    纯css控制文字2行显示多余部分隐藏
  • 原文地址:https://www.cnblogs.com/Answer1215/p/10346485.html
Copyright © 2011-2022 走看看