iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0

嗨大家好,真希望一天能有 48 小時,不然這主題都要分到四部曲了,沒錯,應該會有四部曲! 抱歉了!

Applicative Functor

上次提到了 mapchain 的用法,當然也可以用將多個 State monad 套用在函式參數長度為多個以上

const State = (run) => ({
  run,
  map: (f) =>
    State((a) => {
      const [y, s] = run(a);
      return [f(y), s];
    }),
  chain: (f) =>
    State((x) => {
      const [y, s] = run(x);
      return f(y).run(s);
    }),
  ap: (m) =>
    State((x) => {
      const [y, s] = run(x);
      return m.map(y).run(s);
    }),
});

而這概念也提過很多次,就不多做贅述了~

State.of(1).map(R.add).ap(State.of(1)).run() // [3, undefined]

如果今天是要將一個 Array 內多個 State Monad (Array<State>)進行運算並轉換成 State Array s 呢? 當然也可以還記得在 Traversable 那章提過的嗎? 其要件就是同時要有 Foldable 以及 Functor 的特性

Travserable

首先來記得 Array 也有 traverse 的特性嗎?

Array.prototype.traverse = function (T, f) {
  return this.reduce(
    (acc, val) =>
      f(val)
        .map((x) => (y) => y.concat(x))
        .ap(acc),
    T.of([])
  );
};

在來就是準備多個 State Monad 塞到陣列

const generator = (seed) => {
  const nextSeed = (seed * 1103515245 + 12345) & 0x7fffffff;
  return [nextSeed, nextSeed];
};

const value = (seed) => (seed >>> 16) / 0x7fff;

const normalize = (min, max) => (x) => Math.floor(x * (max - min)) + min;

const randomInRange = (min, max) =>
  State(generator).map(value).map(normalize(min, max));
  
const randomFrom = (from) =>
  randomInRange(0, from.length).map((index) => from[index]);

const FisrtRandom = randomFrom(['FP', 'OOP', 'BOTH']);
const MiddleRandom = randomFrom(['IS', 'ARE']);
const LastRandom = randomFrom(['GOOD', 'SUCK']);

const combineIt = [FisrtRandom, MiddleRandom, LastRandom]

這樣就完成多組同時進行隨機抽取了!!! 猜猜這次的結果會是什麼吧!

const seed = 1;

combineIt.traverse(State, R.identity)
  .map(([x, y, z]) => `${x} ${y} ${z}`)
  .run(seed);
  
// ["FP IS SUCK", 333417792]

Oops! 怎麼會這樣... 突然覺得變搞笑文章系列,Anyway, That's it for today!

小結

感謝大家閱讀!!!

Reference

  1. State Monad

上一篇
Day 27 - State Monad II
下一篇
Day 29 - State Monad IV
系列文
Functional Programming For Everyone30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
juck30808
iT邦研究生 1 級 ‧ 2021-10-14 12:11:26

恭喜即將邁入完賽~/images/emoticon/emoticon08.gif

我要留言

立即登入留言