2016-08-18 83 views
3

对于一个Maybe.Just monad,如果我们用一个返回null的函数来映射它,它仍然会返回Just,但是我认为它应该是Nothing,否则它就失去了防止null的能力。我是对的吗,还是有另外一个原因是这样的?Maybe.map应该尊重映射的值吗?

Maybe.fromNuallable({noname: ''}) // return Just({noname: ''}) 
.map(prop('name')) // return Just(undefined), but I think it should return Nothing() 
.map(x=>x.length) // failed here 

我检查Maybe.map的所有实现(falktale和ramda.fantasy),它是下面:

Just.prototype.map = function(f) { 
    return this.of(f(this.value)); 
}; 
+1

我重写我的答案更好地说明主题 - 主要是为我自己。也许它对其他人也有帮助。 – ftor

+0

非常有帮助,谢谢,尤其是。最后一个转折触及了这一点:每个可能返回null/undefined的函数都应该返回一个Option类型,以便这种行为变得明确 – Ron

回答

1

好吧,我可能是错的,但map来自函子。所以它在简单的态射上运行而不是kleisli箭头。您需要使用bind和某种形式返回一个单子

// maybeProp:: String -> A -> Maybe[B] 
const maybeProp = name => val => Maybe.fromNullable(val[name]) 

Maybe 
    .fromNullable({noname: ''}) 
    .bind(maybeProp('name')) 
    .map(x => x.length) 
+0

感谢您的回答。我认为“绑定”相当于“链条”(这是在幻想世界中定义的)。 “bind”在内部值上应用传递函数并返回一个monad(在这种情况下,它可能是)。所以如果我担心函数会产生空值,我应该使用“bind”而不是“map”。 – Ron

+1

@Ron right。看起来幻想世界中定义的“链”是“绑定”。 'map'又名'fmap'是不够的,因为你想对待内部的空值和未定义的Maybes。所以你需要monad的全部力量来将M [M [A]]“打碎”成M [A]。 –

+0

@ LUH3417这看起来像是Maybe的有效用例。为什么“滥用”? –

1

下面的函数是一个教学大大简化实施Maybe(又名Option)数据类型:

class Option { 
 
    constructor(x) { this.x = x } 
 
    isNone() { return this.x === null || this.x === undefined } 
 
    map(f) { return this.isNone() ? this : this.of(f(this.x)) } 
 
    ap(ftor) { return this.isNone() ? this : ftor.map(this.x) } 
 
    of(x) { return Option.of(x) } 
 
    flatten() { return this.isNone() ? this : this.x } 
 
    chain(mf) { return this.isNone() ? this : this.map(mf).flatten() } 
 
} 
 

 
Option.of = x => new Option(x); 
 

 
const o = new Option({}), 
 
p = new Option({name: "foo"}); 
 

 
const prop = key => o => new Option(o[key]), 
 
len = prop("length"); 
 

 
// 
 
let r1 = o.map(prop("name")).map(x => x.map(len)), 
 
r2 = p.map(prop("name")).map(x => x.map(len)); 
 

 
console.log(r1); 
 
console.log(r2); 
 

 
let r3 = o.chain(prop("name")).chain(len); 
 
r4 = p.chain(prop("name")).chain(len); 
 

 
console.log(r3); 
 
console.log(r4);

  • o and p are Option种类型并实现函子,适用函子和单子接口
  • proplen是Kleisli箭也就是说,返回一个单子(即一个Option单子在这种情况下)
  • ,当你申请prop/leno功能/ p经由它们的仿函数接口(map),则这产生一个嵌套Option型(见r1/r2
  • 避免这种行为需要通过chain(一元的接口)来应用Kleisli箭头,这是的序列和flatten(见r3/r4
  • 每一个可能返回null/undefined应返回Option型,使这一行为变得明确的功能
+1

我可能是错的,但很多书告诉我,也许/无论是处理错误/异常的功能方式。更重要的是,如果对象(我的意思是对象{name:'john'})被传入,我不能控制它是否是正确的方案。 – Ron

+0

@你说得对。 'Maybe/Either'用于处理预期的异常(可能发生)。如果你不能控制对象方案,那么这不是一个运行时异常。我想我需要仔细检查一下主题,然后重写/删除我的答案。 – ftor

+0

感谢您的努力。我正在学习FP,看起来很简单,但当我尝试在现实世界中使用它时,会遇到很多问题。 – Ron