混合fmap和bind(>> =)

时间:2017-01-09 16:15:52

标签: haskell functional-programming coding-style

在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。如果我然后翻转绑定,我会得到更具可读性的东西:

findDlls dir = listDirectoryAbs dir
 >>= filterM predicate3
 >>= return . filter predicate2
 >>= filterM predicate1
 >>= return . f

重写f <$> x - &gt; return . f =<< x - &gt; x >>= return . f以任何方式“糟糕”?在这种情况下,是否有一种避免嵌套表达式的优选方法?

可以使用do符号,但我想避免明确数据流并为每个返回值命名。

1 个答案:

答案 0 :(得分:4)

我不认为这是“坏”(除非它在该特定单子的fmap中丧失优化),但我不喜欢它的冗长。

我宁愿为此定义自己的运算符,<$$> has been suggested<&>会匹配$ / & - 对偶性很好(另请参阅 {{ 3}} 的):

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

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

顺便说一句,如果您的monad是Anyone ever flip (<$>)(例如函数),则<<< / >>>=<< / >>=很好地结合。