[英]How can I avoid explicit recursion in this case?
我结束了这个骨架:
f :: (Monad m) => b -> m ()
f x = traverse_ (f . g x) =<< h x -- how avoid explicit recursion?
g :: b -> a -> b
-- h :: (Foldable t) => b -> m (t a) -- why "Could not deduce (Foldable t0) arising from a use of ‘traverse_’"
h :: b -> m [a]
如何避免f
中的显式递归?
奖励:当我尝试将h
从[]
概括为Foldable
时, f
不会进行类型检查( Could not deduce (Foldable t0) arising from a use of 'traverse_'
)——我做错了什么?
更新:这是真正的代码。 Right
用于递归名称为整数的安全摄像机镜头目录。 Left
是处理名称不是整数的叶子的基本情况。
a <|||> b = left a . right b
doDir (Right d) = traverse_ (doDir . doInt) =<< listDirectory d
where doInt s = ((<|||>) <$> (,) <*> const) (d </> s) $ (TR.readEither :: String -> Either String Int) s
f = doDir
和g ~ doInt
但被重构了一点。 h = listDirectory
。 为了回答奖金,我只是很傻,没有看到我必须结合所有定义来将类型绑定在一起:
f :: (Monad m, Foldable t) => (b -> a -> b) -> (b -> m (t a)) -> b -> m ()
f g h x = traverse_ (f g h . g x) =<< h x
如果您不介意在构建Tree
时泄漏一点内存然后将其丢弃,则可以使用unfoldTreeM
:
f = unfoldTreeM (\b -> (\as -> ((), g b <$> as)) <$> h b)
我不相信有相应的unfoldTreeM_
,但你可以写一个(使用显式递归)。 要概括超出Tree
/ []
连接,您可能还喜欢refoldM
; 如果你在 Hackage 上搜索“hylomorphism”,你可以找到几个类似的函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.