Attach two I / O actions using the same input in Haskell

I have two functions:

emptyDirectory, copyStubFileTo :: FilePath -> IO ()

I want to combine them as shown below:

forM_ ["1", "2"] $\n -> do
  emptyDirectory n
  copyStubFileTo n

Is there any other standard way built into Haskell to simplify this combination? I mean combining two I / O operations and providing them with the same input.

+5
source share
5 answers
liftA2 (>>) emptyDirectory copyStubFileTo
+11
source

Short answer: no, there is no standard way. A slightly longer answer is that you can write a combinator >&>yourself:

(>&>) :: Monad m => (a -> m b) -> (a -> m c) -> a -> m c
(f >&> g) x = f x >> g x

This does exactly what you want to do, as you can see from the types. Using this, you have emptyDirectory >&> copyStubFileTo :: FilePath -> IO (), and therefore

mapM_ (emptyDirectory >&> copyStubFileTo) ["1", "2"]

Hoogle , , , .


>&>, (&) :: (a -> b) -> (a -> c) -> a -> (b,c), . , , , , , ( ), , , ( , ). , - , ; , , Hoogle. ( .)

, (&) :: (a -> b) -> (a -> c) -> a -> (b,c), , . b c, , . : (f & g) x = (f x, g x). pointfree, - :

(&) :: Monad m => m a -> m b -> m (a,b)
(&) = liftM2 (,)

, (r ->) - (-); (&) , (r ->) " -" .

, , emptyDirectory & copyStubFileTo :: FilePath -> (IO (), IO ()). OOG. , tupleM :: Monad m => (m a, m b) -> m (a,b). , & :

tupleM :: Monad m => (m a, m b) -> m (a,b)
tupleM = uncurry (&)

, , ( ).

(&) :

(<&>) :: Monad m => (a -> m b) -> (a -> m c) -> a -> m (b, c)
f <&> g = tupleM . (f & g)

emptyDirectory <&> copyStubFileTo :: FilePath -> IO ((),()), . ( ). (>&>) :: Monad m => (a -> m b) -> (a -> m c) -> a -> m c ( >>), (, , ). - , <.> :: Functor f => (b -> c) -> (a -> f b) -> a -> f c ( <=< Control.Monad).

(<.>) :: Functor f => (b -> c) -> (a -> f b) -> a -> f c
(f <.> g) x = f <$> g x

(>&>) :: (Monad m, Functor m) => (a -> m b) -> (a -> m c) -> a -> m c
f >&> g = snd <.> (f <&> g)

( Functor m, <$> `liftM`.) , >&>. " " >&>; " ". - , ; , , . , : -)

+7

: , , n .

, , ((->) a) Applicative, - :

import Control.Applicative

forM_ ["1", "2"] $ (>>) <$> emptyDirectory <*> copyStubFileTo
+6

- mapM_:

mapM_ ($input) [list of functions]

, :

mapM_ forM_ [emptyDirectory, copyStubFileTo] . flip ($) $ ["1", "2"] 

. .

+4

, , . ( , FUZxxl, )

mapM_ (forM_ [list of inputs]) [list of functions]

mapM_ (forM_ ["foo", "bar"]) [putStrLn, putStrLn . reverse]

Gives out

foo
bar
oof
rab

It can be generalized

xs >.> fs = mapM_ (forM_ xs) fs

So this will lead to the same conclusion

main = ["foo","bar"] >.> [putStrLn, putStrLn . reverse]

Plus, >.>a funny face.

Basically, mapM_ takes a function and a list and applies this function to each member of the list. Therefore, we create a function (forM_ ["foo", "bar"])that has a type (Monad m) => (String -> m b) -> m (). He expects the feature to be introduced. Fortunately for us, every member of the second list is a feature! And therefore, each function in the second list will be transferred to this function of a higher order, creating the desired effect.

0
source

All Articles