Folktale / fantasyland Возможно не работает, как ожидалось - PullRequest
0 голосов
/ 24 мая 2018

Чтение Руководство Frisbys по функциональному программированию , в настоящее время в главе о Maybe.В приложении книга предлагает использовать folktale или fantasyland .

Однако в обеих библиотеках Maybe, похоже, не работаеткак описано в книге.

const Maybe = require('folktale/maybe')
// const Maybe = require('fantasy-options')
const {
    flip, concat, toUpper, path, pathOr, match, prop
} = require('ramda')

console.log(
    Maybe.of('Malkovich Malkovich').map(match(/a/ig))
)
// Just(['a', 'a'])

Maybe.of(null).map(match(/a/ig))
//******************************
// TypeError: Cannot read property 'match' of null
//******************************
// Nothing

Maybe.of(
    { name: 'Boris' }
).map(prop('age')).map(add(10))
// Nothing

Maybe.of(
    { name: 'Dinah', age: 14 }
).map(prop('age')).map(add(10))
// Just(24)

В этом примере, скопированном из книги, первое утверждение работает правильно, но второе получает TypeError.Кажется, это полностью противоречит цели Maybe.Или я что-то неправильно понимаю?

Пример repl.it

1 Ответ

0 голосов
/ 19 августа 2019

Обновление: август 2019

Приятно, что вы задали этот вопрос, я также был изначально удивлен различием в поведении.Как ответили другие, все сводится к тому, как была закодирована реализация Frisby Mostly Adequate Guide .«Нерегулярная» деталь реализации связана со способом, которым реализация функции isNothing s экранирует нулевой или неопределенный value, переданный с использованием Maybe.of:

get isNothing() {
    return this.$value === null || this.$value === undefined;
 }

Если вы ссылаетесь на другие реализации- затем использование Maybe.of() для создания Maybe позволяет вам передать null или undefined для значения Just и фактически вывести, например, Maybe.Just({ value: null })

Вместо этого, когдаИспользуя Folktale, создайте Maybe, используя Maybe.fromNullable(), который будет выделять Just или Nothing в соответствии с введенным значением.

Вот рабочая версия предоставленного кода:

const Maybe = require("folktale/maybe");

const {
  flip,
  concat,
  toUpper,
  path,
  pathOr,
  match,
  prop,
  add
} = require("ramda");

console.log(Maybe.of("Malkovich Malkovich").map(match(/a/gi)));
//-> folktale:Maybe.Just({ value: ["a", "a"] })

console.log(Maybe.fromNullable(null).map(match(/a/gi)));
//-> folktale:Maybe.Nothing({  })

Наконец, вот демонстрационная реализация Maybe, кодифицированная для использования fromNullable (аналогично реализации Folktale).Я взял эту эталонную реализацию из книги, которую я очень рекомендую - Функциональное программирование в JavaScript от Луиса Атенсио .Он проводит большую часть главы 5, объясняя это ясно.

/**
 * Custom Maybe Monad used in FP in JS book written in ES6
 * Author: Luis Atencio
 */ 
exports.Maybe = class Maybe {
    static just(a) {
        return new exports.Just(a);
    }
    static nothing() {
        return new exports.Nothing();
    }
    static fromNullable(a) {
        return a !== null ? Maybe.just(a) : Maybe.nothing();
    }
    static of(a) {
        return Maybe.just(a);
    }
    get isNothing() {
        return false;
    }
    get isJust() {
        return false;
    }
};


// Derived class Just -> Presence of a value
exports.Just = class Just extends exports.Maybe {
    constructor(value) {
        super();
        this._value = value;
    }

    get value() {
        return this._value;
    }

    map(f) {
        return exports.Maybe.fromNullable(f(this._value));
    }

    chain(f) {
        return f(this._value);
    }

    getOrElse() {
        return this._value;
    }

    filter(f) {
        exports.Maybe.fromNullable(f(this._value) ? this._value : null);
    }

    get isJust() {
        return true;
    }

    toString () {
        return `Maybe.Just(${this._value})`;
    }
};

// Derived class Empty -> Abscense of a value
exports.Nothing = class Nothing extends exports.Maybe {
    map(f) {
        return this;
    }

    chain(f) {
        return this;
    }

    get value() {
        throw new TypeError("Can't extract the value of a Nothing.");
    }

    getOrElse(other) {
        return other;
    }

    filter() {
        return this._value;
    }

    get isNothing() {
        return true;
    }   

    toString() {
        return 'Maybe.Nothing';
    }
};
...