今天我试图连接两个 IO 字符串,但无法正常工作。
所以,问题是:假设我们有 s1 :: IO String
和 s2 :: IO String
.如何实现功能(+++) :: IO String -> IO String -> IO String
,其作用与 (++) :: [a] -> [a] -> [a]
完全相同但对于 IO 字符串?
更一般的问题是如何实现更一般的功能 (+++) :: 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
很简单!它所做的只是从两个 monadic 操作中提取值,并将一个带有 2 个参数的函数应用于它们。这与函数
liftM
一起使用它对只有一个参数的函数执行此操作。或者,正如其他人所指出的,您可以使用 IO
的 Applicative
实例在 Control.Applicative
并使用类似的 liftA2
功能。您可能会注意到泛型
Applicative
s 具有与通用 Monad
相似的行为s 在某些情况下,这是因为它们在数学上非常相似。事实上,对于每一个 Monad
,您可以制作 Applicative
从它。因此,您也可以制作 Functor
每个Applicative
.有很多人对Functor-Applicative-Monad proposal感到兴奋这已经存在了一段时间,最终将在即将发布的 GHC 版本中实现。它们形成了一个非常自然的层次结构 Functor > Applicative > Monad
.
关于string - haskell : concat two IO Strings,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20645805/