Please explain (forM_ [stdout, stderr]. Flip hPutStrLn) :: String & # 8594; IO ()

I find it hard to understand how the Haskell expression works:

import Control.Monad
import System.IO
(forM_ [stdout, stderr] . flip hPutStrLn) "hello world"

Which part . flip hPutStrLndoes exactly? Type signatures seem complicated:

ghci> :type flip
flip :: (a -> b -> c) -> b -> a -> c
ghci> :type (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
ghci> :type (. flip)
(. flip) :: ((b -> a -> c1) -> c) -> (a -> b -> c1) -> c
ghci> :type (. flip hPutStrLn)
(. flip hPutStrLn) :: ((Handle -> IO ()) -> c) -> String -> c

What becomes the left and right operands of an operator (.)as an expression is expressed?

Another way to pose the question is: how does the left side of the expression at the top end with a signature of the type as follows:

(forM_ [stdout, stderr] . flip hPutStrLn) :: String -> IO ()
+5
source share
3 answers

The left and right operands (.)are equal

forM_ [stdout, stderr]

and

flip hPutStrLn

respectively.

Type hPutStrLn-

hPutStrLn :: Handle -> String -> IO ()

therefore flip hPutStrLnhas type

flip hPutStrLn :: String -> Handle -> IO ()

As the type system reports, it flipis a combinator that changes the order of other function arguments.

flip       :: (a -> b -> c) -> b -> a -> c
flip f x y =  f y x

ghci , (. flip hPutStrLn)

ghci> :type (. flip hPutStrLn)
(. flip hPutStrLn) :: ((Handle -> IO ()) -> c) -> String -> c

,

ghci> :type forM_ [stdout, stderr]
forM_ [stdout, stderr] :: Monad m => (Handle -> m b) -> m ()

, .

(. flip hPutStrLn)     ::            ((Handle -> IO ()) -> c   ) -> String -> c
forM_ [stdout, stderr] :: Monad m =>  (Handle -> m  b ) -> m ()

( )

ghci> :type forM_ [stdout, stderr] . flip hPutStrLn
forM_ [stdout, stderr] . flip hPutStrLn :: String -> IO ()

String, -, (), .. .

, , , (.). flip , .

+13

flip , :

flip hPutStrLn == \a b -> hPutStrLn b a

. - ( ), . :

forM_ [stdout, stderr] ((flip hPutStrLn) "hello world")

:

forM_ [stdout, stderr] (flip hPutStrLn "hello world")

, :

forM_ [stdout, stderr] $ flip hPutStrLn "hello world"

.. .:

(.) :: (b -> c) -> (a -> b) -> a -> c

: b -> c, a -> b a - c, - Currying, : b -> c a -> b - a -> c. : (forM_ [stdout, stderr] flip hPutStrLn, ), . String -> IO ().

+7

( ).

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

(f . g) :: a -> c      where  g :: (a -> b)  and  f :: (b -> c)

(b a -> b b -> c , a -> c),

flip hPutStrLn         ::    String -> (Handle -> IO ())             -- g
forM_ [stdout, stderr] :: (Monad m) => (Handle -> m  b ) -> m ()     -- f

( Handle -> IO () , , -> ), ( function composition)

(Monad m) => String -> m ()     where  m ~ IO  and b ~ ()
                                (found by unification of
                                        Handle -> IO ()  and
                                        Handle -> m  b       )

. String -> IO ().

(.) ; , . Control.Arrow, >>>, (.) , : (f . g) x == (g >>> f) x.

+2

All Articles