zoukankan      html  css  js  c++  java
  • [Functional Programming] Working with two functors(Applicative Functors)-- Part2 --liftAN

    Let's examine a pointfree way to write these applicative calls. Since we know map is equal to of/ap, we can write generic functions that will ap as many times as we specify:

    const liftA2 = curry((g, f1, f2) => f1.map(g).ap(f2));
    
    const liftA3 = curry((g, f1, f2, f3) => f1.map(g).ap(f2).ap(f3));
    
    // liftA4, etc

    Let's see the previous examples written this way:

    const profile = name => email => `${name}__${email}`;
    const safeProfile = liftA2(profile);
    const res1 = safeProfile(prop('name', user), prop('email', user)); // John Doe__blurp_blurp
    liftA2(add, Maybe.of(2), Maybe.of(3));
    // Maybe(5)
    
    liftA2(renderPage, Http.get('/destinations'), Http.get('/events'));
    // Task('<div>some page with dest and events</div>')
    
    liftA3(signIn, getVal('#email'), getVal('#password'), IO.of(false));
    // IO({ id: 3, email: 'gg@allin.com' })

    liftAN: Lift a curry function into a Functor context, which will be define later;  

    liftA2(add, Maybe.of(2), Maybe.of(3)); Maybe will be the Functor context for 'add' function which has been lifted

    Laws:

    Identity

    // identity
    A.of(id).ap(v) === v;

    For example:

    const v = Identity.of('Pillow Pets');
    Identity.of(id).ap(v) === v;

    Homomorphism

    // homomorphism
    A.of(f).ap(A.of(x)) === A.of(f(x));

    homomorphism is just a structure preserving map. In fact, a functor is just a homomorphism between categories as it preserves the original category's structure under the mapping.

    A quick example:

    Either.of(toUpperCase).ap(Either.of('oreos')) === Either.of(toUpperCase('oreos'));

    Interchange

    The interchange law states that it doesn't matter if we choose to lift our function into the left or right side of ap.

    // interchange
    v.ap(A.of(x)) === A.of(f => f(x)).ap(v);

    Here is an example:

    const v = Task.of(reverse);
    const x = 'Sparklehorse';
    
    v.ap(Task.of(x)) === Task.of(f => f(x)).ap(v);

    Composition

    // composition
    A.of(compose).ap(u).ap(v).ap(w) === u.ap(v.ap(w));
    const u = IO.of(toUpperCase);
    const v = IO.of(concat('& beyond'));
    const w = IO.of('blood bath ');
    
    IO.of(compose).ap(u).ap(v).ap(w) === u.ap(v.ap(w));

    Examples:

    const safeAdd = curry((a, b) => Maybe.of(add).ap(a).ap(b));
    const safeAdd = liftA2(add);
    
    const localStorage = {  
      player1: { id:1, name: 'Albert' },  
      player2: { id:2, name: 'Theresa' },  
    };  
    
    // getFromCache :: String -> IO User  
    const getFromCache = x => new IO(() => localStorage[x]);  
    
    // game :: User -> User -> String  
    const game = curry((p1, p2) => `${p1.name} vs ${p2.name}`);
    // startGame :: IO String
    const startGame = liftA2(game, getFromCache('player1'), getFromCache('player2'));
  • 相关阅读:
    面试十题(4)
    TS中给接口指定的成员?
    TS中定义泛型接口的两种方式
    ts中泛型的使用
    ts中类的属性的封装
    ts中接口的使用
    自定义hook的步骤
    react中如何使用useReducer?
    react中useContext的使用
    react 中useRef的作用
  • 原文地址:https://www.cnblogs.com/Answer1215/p/10441240.html
Copyright © 2011-2022 走看看