使用-在Haskell中加入两个IO

时间:2019-01-16 15:56:45

标签: haskell monads

我需要加入两个IO String,中间插入一个-。这是我想出的,能起作用的-正确的方法是什么?

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

3 个答案:

答案 0 :(得分:7)

您可以在此处使用适用的样式功能:

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

答案 1 :(得分:6)

说实话,您的方法背后的想法实际上对我来说很理智。首先,我可能会使用concat的{​​{1}} intsead,并放一些括号,然后转到:

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

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

答案 2 :(得分:4)

加入两个IO String的一种方法是:

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

我们分别对xy进行“拆箱”,以获取包含的String,然后“用连字符对它们进行重新包装(使用Functor类推)”。

它可以简化为:

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)