如何更改模板字符串推断的值

时间:2019-07-10 11:26:31

标签: javascript node.js functional-programming template-strings

我正在尝试编写一个简单的Id monad来玩耍和学习。

这是我写的:

const util = require('util');

const Id = x => ({
  [util.inspect.custom]: () => `Id(${x})`,
  map: f => Id.of(f(x)),
  flatMap: f => f(x),
  valueOf: () => `Id(${x})`,
});

Id.of = Id;

const foo = Id.of('foo');
const toUpper = str => Id.of(str.toUpperCase());

const fooBoxed = foo.map(toUpper); // Oh oh, should be Id(Id('FOO'));
const FOO = foo.flatMap(toUpper); // Yay, Id('FOO');

console.log(fooBoxed);
console.log(FOO);

fooBoxed应该注销Id(Id(Foo)),但它注销Id([object object])。 我尝试修改valueOfinspect,但两者均无效。我怀疑${x}调用了另一种方法,但我在互联网上找不到。我需要修改什么,以便${x}为嵌套的Id单子返回正确的字符串?

1 个答案:

答案 0 :(得分:2)

您将要覆盖toString,而不是valueOf。与字符串连接(或插入模板字符串)会将值强制转换为字符串,并且您的对象继承Object.prototype.toString并返回[object …]

const Id = x => ({
  toString: () => `Id(${x})`,
  map: f => Id.of(f(x)),
  flatMap: f => f(x),
});

Id.of = Id;

const foo = Id.of('foo');
const toUpper = str => Id.of(str.toUpperCase());

const fooBoxed = foo.map(toUpper);
const FOO = foo.flatMap(toUpper);

console.log(fooBoxed.toString()); // Yay, Id(Id('FOO'));
console.log(FOO.toString()); // Yay, Id('FOO');

但是,由于您似乎打算将其用于调试,因此您实际上应该使用x值的调试表示形式。为此,请自己致电util.inspect()

const util = require('util');

const Id = x => ({
  [util.inspect.custom]: () => `Id(${util.inspect(x)})`,
//                                   ^^^^^^^^^^^^
  map: f => Id.of(f(x)),
  flatMap: f => f(x),
  valueOf: () => x,
});
Id.of = Id;