Haskell:连接两个IO字符串

d12*_*ted 3 string haskell function functor

今天我试图连接两个IO字符串,但无法使它工作.

所以,问题是:假设我们拥有s1 :: IO Strings2 :: IO String.如何实现函数(+++) :: IO String -> IO String -> IO String,它(++) :: [a] -> [a] -> [a]与IO String 完全相同?

更一般的问题是如何实现更一般的功能(+++) :: IO a -> IO a -> IO a?或者甚至更一般?

bhe*_*ilr 17

您可以使用liftM2Control.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仅针对一个参数的功能执行该操作的功能相关.另外,正如有人指出,你可以使用IOApplicative的情况下Control.Applicative,并使用类似的liftA2功能.

您可能会注意到泛型在某些上下文中与泛型Applicatives具有相似的行为Monad,其原因在于它们在数学上非常相似.事实上,对于每一个人来说Monad,你都可以做到Applicative这一点.因此,你也可以做到Functor每一个Applicative.有很多人对Functor-Applicative-Monad提案感到兴奋,该提案已经存在了一段时间,并且最终将在即将推出的GHC版本中实施.他们构成了非常自然的等级制度Functor > Applicative > Monad.

  • @RottenBrain那个答案使用了`IO`的`Applicative`实例.函数`<*>`实际上等同于`Control.Monad.ap`,而`<$>`只是`fmap`的中缀版本,它使用`IO`的`Functor`实例.有时候在Haskell中数学让你以几种不同的方式做某事=) (3认同)
  • 顺便说说.我找到了另一个解决方案.`(++)<$> s1 <*> s2`.它看起来很不错.但现在我真的要冥想我发现的一切:)谢谢你的回答.:) (2认同)

Chr*_*lor 5

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)


The*_*net 5

(++) <$> pure "stringOne" <*> pure "stringTwo" 
Run Code Online (Sandbox Code Playgroud)