PureScript Effects:如何避免深层嵌套并优化类型签名?
调整PureScript中main函数类型签名的最佳方案
你现在的需求是把main的类型从Eff (dom :: DOM) (Maybe (Eff (dom :: DOM) (Maybe Element)))改成Eff (dom :: DOM) (Maybe Element),同时不想修改现有的findItem函数(不想让它处理Maybe逻辑),对吧?
先看你尝试的代码问题出在哪:window >>= document >>= body返回的是Eff (dom :: DOM) (Maybe Element),当你用map findItem <$> ...的时候,map findItem会把Maybe Element转换成Maybe (Eff _ (Maybe Element)),再加上外层的Eff,就得到了你原本不想看到的嵌套类型。
最佳的解决方式是用traverse函数代替map,它能帮你把嵌套的Eff和Maybe结构扁平化,同时不需要改动findItem的定义。
直接上修改后的main代码:
main :: Eff (dom :: DOM) (Maybe Element) main = traverse findItem =<< window >>= document >>= body
如果用do表达式写会更直观,便于理解:
main :: Eff (dom :: DOM) (Maybe Element) main = do maybeBody <- window >>= document >>= body traverse findItem maybeBody
为什么这样可行?
traverse的作用是:当你有一个a -> Eff e b的函数(这里就是findItem),和一个Maybe a(这里是maybeBody),它会返回Eff e (Maybe b)。- 具体来说,如果
maybeBody是Nothing,traverse直接返回pure Nothing;如果是Just e,就执行findItem e,并把结果(Maybe Element)保留在Maybe容器里。 - 这样既保持了
findItem原有的职责(只处理非Maybe的Element),又让main的类型符合你的预期。
内容的提问来源于stack exchange,提问作者M. Walker
相关产品推荐
相关产品推荐

