今天,我尝试连接两个IO字符串,但无法正常工作。
因此,问题是:假设我们有s1 :: IO String
和s2 :: IO String
。如何实现功能(+++) :: IO String -> IO String -> IO String
,该功能(++) :: [a] -> [a] -> [a]
与IO String完全一样?
而更普遍的问题是如何实现更普遍的功能(+++) :: IO a -> IO a -> IO a
?也许更一般?
您可以使用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]
另外,您可以使用do
符号:
(+++) :: Monad m => m [a] -> m [a] -> m [a]
ms1 +++ ms2 = do
s1 <- ms1
s2 <- ms2
return $ s1 ++ s2
这两个都是等效的。实际上,针对的定义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
很简单!它所做的只是从两个单子动作中提取值,并对它们应用2个参数的函数。这与liftM
仅针对一个参数的函数执行此操作的函数相伴。另外,正如其他人指出的那样,您可以在中使用IO
的Applicative
实例Control.Applicative
并使用类似的liftA2
功能。
您可能会注意到,在某些情况下,genericApplicative
具有与generic相似的行为Monad
,其原因是因为它们在数学上非常相似。实际上,对于每个Monad
,您都可以利用Applicative
它。因此,您也可以从中Functor
脱颖而出Applicative
。许多人都对Functor-Applicative-Monad提案感到兴奋,该提案已经存在了一段时间,最终将在即将发布的GHC版本中实施。它们构成一个非常自然的层次结构Functor > Applicative > Monad
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句