bhe*_*ilr 17
您可以使用liftM2从Control.Monad:
liftM2 :: Monad m => (a -> b -> c) -> m a -> m b -> m c
> :t liftM2 (++)
liftM2 (++) :: Monad m => m [a] -> m [a] -> m [a]
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用do符号:
(+++) :: Monad m => m [a] -> m [a] -> m [a]
ms1 +++ ms2 = do
s1 <- ms1
s2 <- ms2
return $ s1 ++ s2
Run Code Online (Sandbox Code Playgroud)
这两者都是等价的.实际上,定义liftM2实现为
liftM2 :: Monad m => (a -> b -> c) -> m a -> m b -> m c
liftM2 f m1 m2 = do
val1 <- m1
val2 <- m2
return $ f val1 val2
Run Code Online (Sandbox Code Playgroud)
非常简单!它所做的就是从两个monadic动作中提取值,并为它们应用2个参数的函数.这与liftM仅针对一个参数的功能执行该操作的功能相关.另外,正如有人指出,你可以使用IO的Applicative的情况下Control.Applicative,并使用类似的liftA2功能.
您可能会注意到泛型在某些上下文中与泛型Applicatives具有相似的行为Monad,其原因在于它们在数学上非常相似.事实上,对于每一个人来说Monad,你都可以做到Applicative这一点.因此,你也可以做到Functor每一个Applicative.有很多人对Functor-Applicative-Monad提案感到兴奋,该提案已经存在了一段时间,并且最终将在即将推出的GHC版本中实施.他们构成了非常自然的等级制度Functor > Applicative > Monad.
import Control.Applicative (liftA2)
(+++) :: Applicative f => f [a] -> f [a] -> f [a]
(+++) = liftA2 (++)
Run Code Online (Sandbox Code Playgroud)
现在在GHCI
>> getLine +++ getLine
Hello <ENTER>
World!<ENTER>
Hello World!
Run Code Online (Sandbox Code Playgroud)