将两个 IO 与 - in haskell 连接



我需要连接两个IO String,中间有一个-。这是我想出的,它有效 - 正确的方法是什么?

import System.Environment
f :: String -> String -> IO String
f x y = (foldl1 (++)) <$> sequence [(getEnv x),(return "-"),(getEnv y)]

您可以在此处使用应用样式函数:

f :: String -> String -> IO String
f x y = withHyp <$> getEnv x <*> getEnv y
    where withHyp ex ey = ex ++ '-' : ey

因此,在这里我们连接两个String,然后通过withHyp函数在中间用连字符连接。

或者对于我们需要获取的环境变量列表,我们可以使用mapM并执行intercalate

import Data.List(intercalate)
f :: [String] -> IO String
f xs = intercalate "-" <$> mapM getEnv xs

实说,你的方法背后的想法对我来说实际上看起来很理智。首先,我可能会使用concat intsead of foldl1 (++) ,并删除一些参数,让我们:

f x y = concat <$> sequence [getEnv x, return "-", getEnv y]

这对我来说真的没有那么糟糕。但是,如果我真的想走得更远,这里有一些想法。首先,我会回忆起intercalate函数。

f x y = intercalate "-" <$> sequence [getEnv x, getEnv y]

还有一个方便的速记,可以将函数应用于列表的每个元素; mapM f = sequence . map f .所以:

f x y = intercalate "-" <$> mapM getEnv [x,y]

我会停在那里;对我来说,它看起来很干净,可以维护。

连接两个IO String的一种方法是:

dash :: IO String -> IO String -> IO String
dash x y = do
    s1 <- x
    s2 <- y
    return $ s1 <> "-" <> s2

我们"拆箱"xy中的每一个,以获得包含的String,然后用连字符"重新装箱"它们(使用函子的类比)。

它可以缩短为:

dash = liftA2 (s1 s2 -> s1 <> "-" <> s2)

其中liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c采用二进制函数并将其"提升"为Applicative s上的二进制函数,这是Monad s的超集。

然后,您的f可以按f x y = dash (getEnv x) (getEnv y)实现。

最新更新