登录
首页 >  文章 >  前端

JavaScript 函数式编程简介:不同的 monad #11

来源:dev.to

时间:2024-07-16 08:27:50 482浏览 收藏

珍惜时间,勤奋学习!今天给大家带来《JavaScript 函数式编程简介:不同的 monad #11》,正文内容主要涉及到等等,如果你正在学习文章,或者是对文章有疑问,欢迎大家关注我!后面我会持续更新相关内容的,希望都能帮到正在学习的大家!

JavaScript 函数式编程简介:不同的 monad #11

monad 是函数式编程中的一个基本概念,它提供了一种以结构化方式处理计算和数据转换的方法。单子有多种类型,每种类型都旨在解决特定问题并处理不同类型的数据和效果。

什么是 monad?

单子是一种抽象,允许对包装值进行链接操作。它由三个主要属性定义:

  1. unit(也称为 of 或 return):接受一个值并将其包装在 monad 中的函数。
  2. bind(也称为 flatmap 或 chain):一个函数,它接受一个 monadic 值和一个返回 monad 的函数,将该函数应用于包装的值,并返回一个新的 monad。
  3. 结合性:一元运算的组合应该是结合性的。

monad 的常见类型

  1. 也许是 monad
  2. monad
  3. 承诺莫纳德
  4. 列出 monad
  5. 读者莫纳德
  6. 作家莫纳德
  7. 状态 monad

1.也许是莫纳德

maybe monad 用于处理可选值。它表示可能失败或返回 null 或未定义的计算。

执行
class maybe {
  constructor(value) {
    this.value = value;
  }

  static of(value) {
    return new maybe(value);
  }

  isnothing() {
    return this.value === null || this.value === undefined;
  }

  map(fn) {
    return this.isnothing() ? this : maybe.of(fn(this.value));
  }

  flatmap(fn) {
    return this.isnothing() ? this : fn(this.value);
  }
}

// usage
const maybevalue = maybe.of('hello')
  .map(str => str.touppercase())
  .flatmap(str => maybe.of(`${str} world`));
console.log(maybevalue); // maybe { value: 'hello world' }

2. 任一 monad

either monad 用于处理可以返回成功值(右)或错误值(左)的计算。

执行
class either {
  constructor(value, isright = true) {
    this.value = value;
    this.isright = isright;
  }

  static right(value) {
    return new either(value, true);
  }

  static left(value) {
    return new either(value, false);
  }

  map(fn) {
    return this.isright ? either.right(fn(this.value)) : this;
  }

  flatmap(fn) {
    return this.isright ? fn(this.value) : this;
  }
}

// usage
const rightvalue = either.right(5)
  .map(x => x + 1)
  .flatmap(x => either.right(x * 2));
console.log(rightvalue); // either { value: 12, isright: true }

const leftvalue = either.left('error')
  .map(x => x + 1)
  .flatmap(x => either.right(x * 2));
console.log(leftvalue); // either { value: 'error', isright: false }

3. 承诺单子

promise monad 用于处理异步计算。

用法
const fetchdata = url => {
  return new promise((resolve, reject) => {
    settimeout(() => {
      resolve(`data from ${url}`);
    }, 1000);
  });
};

// usage
fetchdata('https://api.example.com')
  .then(data => {
    console.log(data); // 'data from https://api.example.com'
    return fetchdata('https://api.example.com/2');
  })
  .then(data => {
    console.log(data); // 'data from https://api.example.com/2'
  })
  .catch(error => {
    console.error(error);
  });

4. 列出单子

list monad 用于处理生成值列表的计算。

执行
class list {
  constructor(values) {
    this.values = values;
  }

  static of(values) {
    return new list(values);
  }

  map(fn) {
    return list.of(this.values.map(fn));
  }

  flatmap(fn) {
    return list.of(this.values.flatmap(value => fn(value).values));
  }
}

// usage
const list = list.of([1, 2, 3])
  .map(x => x + 1)
  .flatmap(x => list.of([x, x * 2]));
console.log(list); // list { values: [ 2, 4, 3, 6, 4, 8 ] }

5. 读者单子

reader monad 用于处理依赖于某些共享环境或配置的计算。

执行
class reader {
  constructor(fn) {
    this.fn = fn;
  }

  static of(value) {
    return new reader(() => value);
  }

  map(fn) {
    return new reader(env => fn(this.fn(env)));
  }

  flatmap(fn) {
    return new reader(env => fn(this.fn(env)).fn(env));
  }

  run(env) {
    return this.fn(env);
  }
}

// usage
const config = { baseurl: 'https://api.example.com' };

const fetchuser = new reader(env => `${env.baseurl}/user`);
const fetchposts = new reader(env => `${env.baseurl}/posts`);

const fetchuserandposts = fetchuser.flatmap(userurl =>
  fetchposts.map(postsurl => ({ userurl, postsurl }))
);

console.log(fetchuserandposts.run(config)); 
// { userurl: 'https://api.example.com/user', postsurl: 'https://api.example.com/posts' }

6.作家莫纳德

writer monad 用于处理生成值以及日志或附加数据的计算。

执行
class writer {
  constructor(value, log) {
    this.value = value;
    this.log = log;
  }

  static of(value) {
    return new writer(value, '');
  }

  map(fn) {
    const result = fn(this.value);
    return new writer(result.value, this.log + result.log);
  }

  flatmap(fn) {
    const result = fn(this.value);
    return new writer(result.value, this.log + result.log);
  }

  tell(log) {
    return new writer(this.value, this.log + log);
  }
}

// usage
const writer = writer.of(3)
  .map(value => new writer(value + 1, 'incremented\n'))
  .flatmap(value => new writer(value * 2, 'doubled\n'));

console.log(writer); 
// writer { value: 8, log: 'incremented\ndoubled\n' }

7. 状态单子

state monad 用于处理维护状态的计算。

执行
class State {
  constructor(runState) {
    this.runState = runState;
  }

  static of(value) {
    return new State(state => [value, state]);
  }

  map(fn) {
    return new State(state => {
      const [value, newState] = this.runState(state);
      return [fn(value), newState];
    });
  }

  flatMap(fn) {
    return new State(state => {
      const [value, newState] = this.runState(state);
      return fn(value).runState(newState);
    });
  }

  run(initialState) {
    return this.runState(initialState);
  }
}

// Usage
const increment = new State(state => [state + 1, state + 1]);

const result = increment
  .flatMap(() => increment)
  .flatMap(() => increment)
  .run(0);

console.log(result); // [3, 3]

结论

monad 提供了一种结构化且可预测的方式来处理函数式编程中的计算和数据转换。每种类型的 monad 都有特定的用途,从使用 maybe monad 处理可选值到使用 promise monad 管理异步操作。

本篇关于《JavaScript 函数式编程简介:不同的 monad #11》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于文章的相关知识,请关注golang学习网公众号!

声明:本文转载于:dev.to 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>