我想定义一个记录器功能,比如
myPutStrLn = putStrLn . (++) "log: " main = do myPutStrLn "hello"
这很好.现在我想用printf格式化提供的String,就像这样
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 composition的东西,但我无法将其应用于我的问题.我甚至不确定它是否能解决我的问题.
解决方法
您可以使用hPrintf和stdout句柄定义您的函数.
像这样,函数myPrintf的结果仍然是类HPrintfType的一个实例
myPrintf:: (HPrintfType c) => String -> c myPrintf = (hPrintf stdout) . (printf "log:%s") main = myPrintf "test %d" (23 :: Int)
printf函数的polyvariadic形式仅适用于您具有此实例定义:
(PrintfArg a,PrintfType r) => PrintfType (a -> r).
在每个新的PrintfArg参数中,如果可能,类型推断返回PrintfType类类型.
对于工作,您的记录器功能将具有以下类型:
logger :: (PrintfType c) => String -> c
但是编译器会失败,因为函数返回IO()而不是更通用的类型类PrintfType.
在我看来,只有模块Text.Printf的修改可以帮助你,因为你无法创建PrintfType的新实例,因为某些方法被隐藏
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。