可能是javascript解释中的monad示例代码
我正在开始或尝试学习函数式编程单子 所以第一个可能是。我想用monad转换代码可能是javascript解释中的monad示例代码,javascript,functional-programming,Javascript,Functional Programming,我正在开始或尝试学习函数式编程单子 所以第一个可能是。我想用monad转换代码 function(fieldName, vals, fields) { var newValue = vals[fieldName]; if (typeof(newValue) == 'undefined') { var elemFrom = fields[fieldName]; if (elemFrom) { newValue = fields
function(fieldName, vals, fields) {
var newValue = vals[fieldName];
if (typeof(newValue) == 'undefined') {
var elemFrom = fields[fieldName];
if (elemFrom) {
newValue = fields[fieldName]
}
}
if (typeof (newValue) != 'undefined') {
return newValue
}
}
这里我有一堆未定义的检查,我认为这是monay的一个很好的用途
我的问题是,我读到您将值传递给maybe monad和map函数
但是在我的例子中,我替换了monad中的值
如果我传递null,map方法将不执行任何操作,因为该值未定义
我没有使用框架,我想要简单的实现,这样我才能理解它
我应该在maybe monad类(函数)中添加“else”方法吗
我有一个相反的情况“如果值未定义,则执行某些操作”
你能建议如何解决这个问题吗
谢谢因此您发布的函数可以重写为
const f = (a, b, c) => b[a] === undefined ? c[a] : b[a];
我不清楚这是否需要成为一个函数,而不是内联到任何你想使用相关对象属性的地方,但也许你只是部分地应用了它或其他什么,我不是在判断
至于Maybe,一个(非常简单的)实现可能如下所示:
class Maybe {
static of (value) {
return new Maybe(value);
}
// Proper solution here should be recursive to handle
// nesting properly, but I'm lazy
static equals (a, b) {
return a.chain(x => x) === b.chain(x => x);
}
constructor(value) {
this._value = value;
}
map (f) {
// Does not distinguish null from undefined, but YMMV. Note
// that if the Maybe value is null or undefined we never touch
// f, that's the null propagation thing.
return this._value == null ? this : new Maybe(f(this._value));
}
chain (f) {
const result = this._value == null ? this : f(this._value);
console.assert(result instanceof Maybe);
return result;
}
}
const or = (a, b) => {
return Maybe.of(a == null ? b : a);
}
现在我们可以测试它是否符合单子定律:
const a = 3;
const f = x => Maybe.of(x * x);
Maybe.of(a).chain(f) === f(a) // left identity
Maybe.equals(Maybe.of(5).chain(Maybe.of), Maybe.of(5)); // right identity
这是一个有效的函子
Maybe.equals(Maybe.of(3).map(x => x), Maybe.of(3)); // identity
Maybe.equals( // composition
Maybe.of(3).map(x => x + 2).map(x => x * 3),
Maybe.of(3).map(compose(x => x * 3, x => x + 2))
);
好极了
现在,来谈谈你的函数。它将被改写为
const f = (a, b, c) => {
return b[a] === undefined ? Maybe.of(c[a]) : Maybe.of(b[a]);
}
也许你现在明白我困惑的原因了,也许这并没有给你带来多少好处。但是如果我用的话,也许我会把整个事情改写成这样:
class Maybe {
static of (value) {
return new Maybe(value);
}
// Proper solution here should be recursive to handle
// nesting properly, but I'm lazy
static equals (a, b) {
return a.chain(x => x) === b.chain(x => x);
}
constructor(value) {
this._value = value;
}
map (f) {
// Does not distinguish null from undefined, but YMMV. Note
// that if the Maybe value is null or undefined we never touch
// f, that's the null propagation thing.
return this._value == null ? this : new Maybe(f(this._value));
}
chain (f) {
const result = this._value == null ? this : f(this._value);
console.assert(result instanceof Maybe);
return result;
}
}
const or = (a, b) => {
return Maybe.of(a == null ? b : a);
}
然后我只需传入属性访问:
const obj1 = { a: 2, c: 3 };
const obj2 = { b: 4 };
const prop = "a"
const result = or(obj1["prop"], obj2["prop"]); // Maybe(2)
使现代化
值得称赞的是@Bergi在评论中提醒我关于替代方案。您可以向上面的Maybe类添加一个方法,如下所示:
alt (x) {
if (!(x instanceof Maybe)) {
throw new TypeError("Expected a Maybe");
}
return this.chain(x => x) == null ? x : this;
}
// semantics
Maybe.of(null).alt(Maybe.of(3)); // Maybe(3)
Maybe.of(2).alt(Maybe.of(4)); // Maybe(2)
// usage
Maybe.of(obj1[prop]).alt(Maybe.of(obj2[prop]));
注意,这并不能完全满足作为替代方法的实现(您还需要一个零/空方法),但您可以阅读和了解更多详细信息。这可能是您发布的函数的最佳替代品。您发布的代码没有任何一元性。你真正的问题是什么?另外,如果你想学习FP,单子是一个糟糕的起点。问题的关键是我如何用Maybe monad翻译代码,因为我不能“我读到你把值传递给Maybe monad和map函数”-嗯,要使用单子,你要使用
chain
函数(或bind
或flatMap
或其他任何名称)我添加了JavaScript标记。以后请务必添加该标记,语法突出显示依赖于它:)您可能希望在Maybe
数据类型上实现一个备选实例-这就是这里实际需要的。@Bergi谢谢,在Control.Applicative中添加了一个快速而肮脏的方法,其中包含到幻想世界和可选类的链接。如果我遗漏了任何其他内容,请告诉我。我认为应该是可能。from(null)。alt(可能。from(3))
@Bergi修复了它。回顾这一点,您的chain
方法似乎完全不正确。它应该简单地读取并返回此值。\u value==null?这个:f(这个值)
(其中f(此._值)
可以断言为实例,可能是
-而不是任何monad)。