在 Haskell 中,当我必须混合调用 fmap
/<$>
和 >>=
/=<<
时,我总是以很多括号结束。
例如,这里我调用 listDirectoryAbs dir :: IO [String]
,然后链接一系列 filter
和 filterM
,以 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/