我需要加入两个IO String
,中间插入一个-
。这是我想出的,能起作用的-正确的方法是什么?
import System.Environment
f :: String -> String -> IO String
f x y = (foldl1 (++)) <$> sequence [(getEnv x),(return "-"),(getEnv y)]
答案 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
我们分别对x
和y
进行“拆箱”,以获取包含的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)
。