我经常发现自己想要将常规函数插入“绑定”序列中。就像在这个人为的例子中一样:
getLine >>= lift (map toUpper) >>= putStrLn
我需要定义提升功能lift :: (a -> b) -> a -> m b
才能使其正常工作。问题是我不知道这样的功能,Hoogle似乎也没有。我觉得这很奇怪,因为这对我来说很有意义。
现在,可能有其他方法可以使这项工作,但我喜欢无点样式代码允许我在一遍中扫描线以找出正在发生的事情的方式。
let lift f x = return (f x) in
getLine >>= lift (map toUpper) >>= putStrLn
我的问题归结为:我错过了什么或者怎么没有像升力这样的功能。我在Haskell的经历仍然非常有限,所以我假设大多数人以不同的方式解决这个问题。有人可以向我解释解决这个问题的惯用方法。
答案 0 :(得分:18)
有三种惯用方式。
不要使用bind;请使用您的Hoogle搜索中的第一个匹配:
liftM (map toUpper) getLine >>= putStrLn
liftM
有多种替代拼写,例如fmap
或(<$>)
。
内联您定义的lift
函数:
getLine >>= return . map toUpper >>= putStrLn
使用monad定律融合选项2中的最后两个绑定:
getLine >>= putStrLn . map toUpper
答案 1 :(得分:3)
在这种情况下使用Functor
实例:
> import Data.Char
> import Data.Functor
> map toUpper <$> getLine >>= putStrLn
foo
FOO
>