[Functional Programming] Working with two functors(Applicative Functors)-- Part1 --.ap

What is applicative functor:

the ability to apply functors to each other.

For example we have tow functors: Container(2), Container(3)

// We can't do this because the numbers are bottled up.
add(Container.of(2), Container.of(3));  // NaN

We cannot just add two functors!

 

Instead we should do:

const map = (fn, m) => m.map(fn);
const containerOfAdd2 = map(add(3), Container.of(2)); // Container(5)

or

Container.of(2).chain(two => Container.of(3).map(add(two)));

 

Previous solution should work. but there are better way to do it:

1. ap

Container.prototype.ap = function (otherContainer) {
  return otherContainer.map(this.$value);
};

As you can see, 'ap' takes a fuctor then applya map to it.

We can see ap:

Container.of(2).map(add).ap(Container.of(3)); // Container(5)

Or, we add lift 'add(2)' into Container, then apply Container(3):

Container.of(add(2)).ap(Container.of(3)); // Container(5)

Because 'add' is partially  applied in add(2), when doing '.ap(Container.of(3))', we give the rest input '3' to it.

Now, we can define applicative functor in programming language:

An applicative functor is a pointed functor with an ap method

Note the dependence on pointed

 

Laws behind:

F.of(x).map(f) === F.of(f).ap(F.of(x))

Main idea is: lift 'f' (function) into Functor, then 'ap' (apply) another Functor with the value (x).

Some example:

Maybe.of(add).ap(Maybe.of(2)).ap(Maybe.of(3)) // Just(5)
Task.of(add).ap(Task.of(2)).ap(Task.of(3)) // Task(5)

Equals:

Maybe.of(add(2)).ap(Maybe.of(3)) // Just(5)
Task.of(add(2)).ap(Task.of(3)) // Task(5)

 

More examples:

// Http.get :: String -> Task Error HTML

const renderPage = curry((destinations, events) => { /* render page */ });

Task.of(renderPage).ap(Http.get('/destinations')).ap(Http.get('/events'));
// Task("<div>some page with dest and events</div>")
复制代码
// $ :: String -> IO DOM
const $ = selector => new IO(() => document.querySelector(selector));

// getVal :: String -> IO String
const getVal = compose(map(prop('value')), $);

// signIn :: String -> String -> Bool -> User
const signIn = curry((username, password, rememberMe) => { /* signing in */ });

IO.of(signIn).ap(getVal('#email')).ap(getVal('#password')).ap(IO.of(false));
// IO({ id: 3, email: 'gg@allin.com' })
复制代码

 

----

  

posted @   Zhentiw  阅读(216)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2018-02-25 [ES2018] Two ways to write for-await-of
2016-02-25 [RxJS] Using Observable.create for fine-grained control
点击右上角即可分享
微信分享提示