我嘗試將traverse
/sequenceA
翻譯爲Javascript。現在,Haskell的實現的下面的行爲給我的麻煩:顯式類型傳遞不等於類型推斷(就表現力而言)?
traverse (\x -> x) Nothing -- yields Nothing
sequenceA Nothing -- yields Nothing
traverse (\x -> x) (Just [7]) -- yields [Just 7]
sequenceA (Just [7]) -- yields [Just 7]
作爲一個Haskell新手我不知道爲什麼第一個表達式在所有工作:
instance Traversable Maybe where
traverse _ Nothing = pure Nothing
traverse f (Just x) = Just <$> f x
pure Nothing
不應該在這種情況下工作,因爲有沒有最小的應用上下文中的價值可以放進去。看起來好像編譯器檢查這個表達式的類型懶惰,因爲映射id函數Nothing
是一個noop,它只是「忽略」類型錯誤,所以說話。
這裏是我的Javascript翻譯:
(請注意,因爲Javascirpt的原型系統是不夠的一對夫婦類型的類並沒有嚴格的類型檢查,無論如何,我與教會的編碼工作,並通過類型約束功能明確。)
// minimal type system realized with `Symbol`s
const $tag = Symbol.for("ftor/tag");
const $Option = Symbol.for("ftor/Option");
const Option = {};
// value constructors (Church encoded)
const Some = x => {
const Some = r => {
const Some = f => f(x);
return Some[$tag] = "Some", Some[$Option] = true, Some;
};
return Some[$tag] = "Some", Some[$Option] = true, Some;
};
const None = r => {
const None = f => r;
return None[$tag] = "None", None[$Option] = true, None;
};
None[$tag] = "None";
None[$Option] = true;
// Traversable
// of/map are explicit arguments of traverse to imitate type inference
// tx[$Option] is just duck typing to enforce the Option type
// of == pure in Javascript
Option.traverse = (of, map) => ft => tx =>
tx[$Option] && tx(of(None)) (x => map(Some) (ft(x)));
// (partial) Array instance of Applicative
const map = f => xs => xs.map(f);
const of = x => [x];
// helpers
const I = x => x;
// applying
Option.traverse(of, map) (I) (None) // ~ [None]
Option.traverse(of, map) (I) (Some([7])) // ~ [Some(7)]
顯然,這種轉換從Haskell實現的偏離,因爲我得到一個[None]
,我應該得到一個None
。老實說,這種行爲恰好與我的直覺相對應,但我認爲直覺在函數式編程中沒有幫助。現在我的問題是
- 我只是做了一個菜鳥的錯誤?
- 還是顯式類型傳遞不等於類型推斷(就表現力而言)?
這是菜鳥的錯誤! – ftor