Составление функции с помощью Text.Printf.printf

Я хотел бы определить функцию журнала, как

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

что хорошо Теперь я хочу отформатировать предоставленную строку с printf, как это

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

Большой! Так как у меня есть этот образец очень часто, я хочу учесть printf в функцию логгера:

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)

К сожалению, это не с

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 выводит myPrintf :: String -> IO (), так что, очевидно, что-то не так. Я нашел кое-что о композиции Polyvariadic, но я не могу применить это к моей проблеме. Я даже не уверен, решит ли это мою проблему.

Код также доступен через гист.

1 ответ

Вы можете определить свою функцию, используя hPrintf и дескриптор stdout.

Таким образом, результат функции myPrintf остается экземпляром класса HPrintfType

myPrintf::  (HPrintfType c) => String -> c
myPrintf = (hPrintf stdout) . (printf "log:%s")

main = myPrintf "test %d" (23 :: Int)

Поливариадная форма для функции printf работает только потому, что у вас есть это определение экземпляра:

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

при каждом новом параметре PrintfArg вывод типа возвращает тип класса PrintfType, если это возможно.

Для работы вашей функции регистрации будет иметь следующий тип:

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

но компилятор потерпит неудачу, потому что функция возвращает IO (), а не более общий класс типов PrintfType.

На мой взгляд, только модификация модуля Text.Printf может помочь вам, потому что вы не можете создать новый экземпляр PrintfType, так как некоторые методы скрыты

Другие вопросы по тегам