تعد Monads مفهومًا أساسيًا في البرمجة الوظيفية التي توفر طريقة للتعامل مع الحسابات وتحويلات البيانات بطريقة منظمة. هناك أنواع مختلفة من المونادات، كل منها مصمم لحل مشكلات معينة والتعامل مع أنواع مختلفة من البيانات والتأثيرات.
الموناد هو تجريد يسمح بتسلسل العمليات على القيم الملتفة. يتم تعريفه من خلال ثلاث خصائص أساسية:
يتم استخدام ربما Monad للتعامل مع القيم الاختيارية. إنه يمثل عملية حسابية قد تفشل أو تُرجع فارغة أو غير محددة.
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' }
يتم استخدام إما 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 }
يتم استخدام 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); });
يتم استخدام 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 ] }
يتم استخدام 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' }
يتم استخدام 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' }
يتم استخدام 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]
توفر Monads طريقة منظمة ويمكن التنبؤ بها للتعامل مع الحسابات وتحويلات البيانات في البرمجة الوظيفية. يخدم كل نوع من أنواع الموناد غرضًا محددًا، بدءًا من التعامل مع القيم الاختيارية باستخدام Maybe Monad وحتى إدارة العمليات غير المتزامنة باستخدام Promise Monad.
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3