簡體   English   中英

Haskell:連接兩個IO字符串

[英]Haskell : concat two IO Strings

今天我試圖連接兩個IO字符串,但無法使它工作。

所以,問題是:假設我們有s1 :: IO Strings2 :: IO String 如何實現函數(+++) :: IO String -> IO String -> IO String ,與(++) :: [a] -> [a] -> [a]完全相同但是對於IO字符串?

更一般的問題是如何實現更通用的功能(+++) :: IO a -> IO a -> IO a 或者甚至更一般?

您可以使用Control.Monad liftM2

liftM2 :: Monad m => (a -> b -> c) -> m a -> m b -> m c


> :t liftM2 (++)
liftM2 (++) :: Monad m => m [a] -> m [a] -> m [a]

或者,您可以使用do notation:

(+++) :: 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執行,該函數僅對一個參數執行此操作。 或者,正如其他人所指出的,您可以在Control.Applicative使用IOApplicative實例,並使用類似的liftA2函數。

您可能會注意到泛型Applicative在某些上下文中具有與通用Monad相似的行為,其原因在於它們在數學上非常相似。 事實上,對於每一個Monad ,你可以用它來制作一個Applicative 因此,您還可以從每個Applicative創建一個Functor 有很多人對Functor-Applicative-Monad提案感到興奮,該提案已經存在了一段時間,並且最終將在即將推出的GHC版本中實施。 它們構成了Functor > Applicative > Monad的非常自然的層次結構。

import Control.Applicative (liftA2)

(+++) :: Applicative f => f [a] -> f [a] -> f [a]
(+++) = liftA2 (++)

現在在GHCI

>> getLine +++ getLine
Hello <ENTER>
World!<ENTER>
Hello World!
(++) <$> pure "stringOne" <*> pure "stringTwo" 

實現函數(+++) ...與(++) :: [a] -> [a] -> [a]但對於IO String

不要這樣做,這是一個壞主意。 連接字符串是一個純功能操作,沒有理由在IO monad中使用它。 除了你需要結果的地方 - 我想在其他IO的中間某個地方。 那么,只需使用do -notation將讀取的字符串綁定到變量名稱,並在它們上使用普通(++)

do
  print "Now start obtaining strings..."
  somePreliminaryActions
  someMoreIOStuff
  s1 <- getS1
  s2 <- getS2
  yetMoreIO
  useConcat'dStrings (s1 ++ s2)
  print "Done."

通過編寫s12 <- liftA2 (++) getS1 getS2可以使其更緊湊。 但我會在適當的位置做到這一點,而不是單獨定義它。

對於較長的操作,您當然可能希望定義一個單獨的命名操作,但它應該是一個有意義的操作。

您不應該將IO String對象視為“IO-strings”。 它們不是,就像[Int]不是“列表整數”一樣。 IO String類型的對象是一個動作 ,當它發生時,可以在IO monad中提供String對象。 它本身不是一個字符串。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM