2016-08-18 66 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