I would like to define a logger function, like
myPutStrLn = putStrLn . (++) "log: "
main = do myPutStrLn "hello"
which is fine. Now I want to format the provided String with printf
, like this
myPutStrLn $ printf "test %d" (23 :: Int)
Great! Since I have this pattern very often I want to factor printf
into the logger 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 infers myPrintf :: String -> IO ()
, so there is obviously something wrong. I found something about Polyvariadic composition, but I'm not able to apply this to my problem. I'm not even sure if it would solve my problem.
The code is also available via gist.
you can define your function by using hPrintf and the stdout handle.
Like that, the result of the function myPrintf remain an instance of the class HPrintfType
myPrintf:: (HPrintfType c) => String -> c
myPrintf = (hPrintf stdout) . (printf "log:%s")
main = myPrintf "test %d" (23 :: Int)
The polyvariadic form for the printf function works only because you have this instance definition :
(PrintfArg a, PrintfType r) => PrintfType (a -> r).
at each new PrintfArg parameter, type inference return an PrintfType class type if possible.
For working your logger function would have the following type :
logger :: (PrintfType c) => String -> c
but the compilator wil fail because the function return an IO () and not the more generic typeclass PrintfType.
In my opinion, only a modification of the module Text.Printf could help you because you can't create new instance of PrintfType as some method are hidden
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With