在 Haskell 中,当我必须混合调用 fmap/<$>>>=/=<< 时,我总是以很多括号结束。

例如,这里我调用 listDirectoryAbs dir :: IO [String] ,然后链接一系列 filterfilterM ,以 fmap 结尾。

findDlls :: String -> IO [String]
findDlls dir = f <$> (filterM predicate1 =<< (filter predicate2 <$> (filterM predicate3 =<< listDirectoryAbs dir)))

因为所有这些嵌套表达式看起来很乱(至少对我来说),所以我最终将 f <$> x 重写为 return . f =<< x 。如果我然后翻转绑定(bind),我会得到一些更具可读性的东西:
findDlls dir = listDirectoryAbs dir
 >>= filterM predicate3
 >>= return . filter predicate2
 >>= filterM predicate1
 >>= return . f

是否以任何方式重写 f <$> x -> return . f =<< x -> x >>= return . f “坏”?在这种情况下,是否有更好的方法来避免嵌套表达式?

我可以改用 do 表示法,但我想避免必须明确说明数据流并为每个返回值指定一个名称。

最佳答案

我不认为它是“坏的”(除非它放弃了对该特定 monad 的 fmap 的优化),但是我不喜欢它的冗长。

我宁愿为此定义我自己的运算符, <$$> has been suggested<&> 将匹配 $ / & -duality(另见 Anyone ever flip (<$>) ):

infixl 1 <&>
(<&>) = flip (<$>)

findDlls dir = listDirectoryAbs dir
 >>= filterM predicate3
 <&> filter predicate2
 >>= filterM predicate1
 <&> f

顺便说一句,如果您的 monad 是 Arrow (例如函数),那么 <<</>>>=<</>>= 结合得很好。

关于haskell - 混合 fmap 和绑定(bind) (>>=),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41552250/

10-12 03:28