Functional Composition with Text.Printf.printf

I would like to define a logger function like

myPutStrLn = putStrLn . (++) "log: " main = do myPutStrLn "hello" 

what well. Now I want to format the provided String with printf , like this

 myPutStrLn $ printf "test %d" (23 :: Int) 

Excellent! Since I often use this scheme, I want to include printf in the registration function:

 myPrintf = logger . printf where -- note, this is just an example. should be -- replaceable with any function with this -- typesignature logger :: String -> IO () logger = putStrLn . (++) "log: " main = myPrintf "test %d" (23 :: Int) 

Unfortunately this fails with

 The function `myPrintf' is applied to two arguments, but its type `String -> IO ()' has only one In a stmt of a 'do' block: myPrintf "test %d" (23 :: Int) In the expression: do { myPrintf "test %d" (23 :: Int) } In an equation for `main': main = do { myPrintf "test %d" (23 :: Int) } 

GHC outputs myPrintf :: String -> IO () , so obviously something is wrong. I found something about Polyvariadic composition , but I can not apply this to my problem. I'm not even sure that this will solve my problem.

Code is also available through gist .

+4
source share
1 answer

you can define your function using hPrintf and the stdout descriptor.

Thus, the result of the myPrintf function remains an instance of the HPrintfType class

 myPrintf:: (HPrintfType c) => String -> c myPrintf = (hPrintf stdout) . (printf "log:%s") main = myPrintf "test %d" (23 :: Int) 

The polyvarian form for the printf function only works because you have this instance definition:

 (PrintfArg a, PrintfType r) => PrintfType (a -> r). 

in each new PrintfArg parameter, enter the output; if possible, enter the class type PrintfType.

The following type will be specified for your log function to work:

 logger :: (PrintfType c) => String -> c 

but the wil compiler fails because the function returns IO (), not the more general type of the PrintfType class.

In my opinion, only a modification of the Text.Printf module can help you, because you cannot create a new PrintfType instance, because some method is hidden

+1
source

All Articles