Reputation: 3943
I need to join two IO String
s with a -
in between. Here's what I came up with, which works - what's the right way?
import System.Environment
f :: String -> String -> IO String
f x y = (foldl1 (++)) <$> sequence [(getEnv x),(return "-"),(getEnv y)]
Upvotes: 4
Views: 227
Reputation: 153162
I'll be honest, the idea behind your approach actually looks pretty sane to me. To start with, I'd probably use concat
intsead of foldl1 (++)
, and drop some parens, getting us to:
f x y = concat <$> sequence [getEnv x, return "-", getEnv y]
This really doesn't seem that bad to me. But if I really wanted to push farther, here's some thoughts I would have. First, I'd recall the intercalate
function.
f x y = intercalate "-" <$> sequence [getEnv x, getEnv y]
There's a handy shorthand for applying a function to each element of a list, too; mapM f = sequence . map f
. So:
f x y = intercalate "-" <$> mapM getEnv [x,y]
I would stop there; it looks quite clean and maintainable to me.
Upvotes: 6
Reputation: 477318
You could here use an applicative style function:
f :: String -> String -> IO String
f x y = withHyp <$> getEnv x <*> getEnv y
where withHyp ex ey = ex ++ '-' : ey
So here we join the two String
s that are then joined with a hypen in the middle through the withHyp
function.
Or for a list of environment variables that we need to fetch, we can use mapM
and perform an intercalate
:
import Data.List(intercalate)
f :: [String] -> IO String
f xs = intercalate "-" <$> mapM getEnv xs
Upvotes: 7
Reputation: 6037
One way of joining two IO String
s would be:
dash :: IO String -> IO String -> IO String
dash x y = do
s1 <- x
s2 <- y
return $ s1 <> "-" <> s2
We "unbox" each of x
and y
to get the contained String
s, then "rebox` them with a hyphen (using the analogy for Functors).
It can be shortened to:
dash = liftA2 (\s1 s2 -> s1 <> "-" <> s2)
Where liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
takes a binary function and "lifts" it into a binary function on Applicative
s, which are a superset of Monad
s.
Your f
can then be implemented as f x y = dash (getEnv x) (getEnv y)
.
Upvotes: 4