Text.Printf 的类型安全替代方案是 formatting 包。 Text.Printf.printf 不确保在编译时格式化参数的数量与参数的数量及其类型一致。阅读 Chris Done 的文章,What's wrong with printf? 以获取示例。
示例用法:
{-# LANGUAGE OverloadedStrings #-}
import Formatting
map (uncurry $ formatToString ("Value: " % int % " " % int)) [(1,100), (2,350), ...]
map (\(x,y) -> formatToString ("Value: " % int % " " % int) x y) [(1,100), (2,350), ...]
它需要 GHC 扩展 OverloadedStrings 才能正常运行。
虽然formatToString ("Value: " % int % " " % int) 具有Int -> Int -> String 类型,但取消curry 会给出(Int, Int) -> String 类型,其输入类型与列表中的元素匹配。
重写过程可以分解;假设f = formatString ("Value: " ...),
map (\(x,y) -> f x y) ≡ map (\(x,y) -> uncurry f (x,y)) ≡ map (uncurry f)
也就是说,首先你 uncurry f 来实现接受元组的函数,然后你执行一个常规的Eta-conversion,因为\(x,y) -> uncurry f (x,y) 等同于简单的uncurry f。要打印结果中的每一行,请使用mapM_:
mapM_ (putStrLn . uncurry $ formatToString ...) [(1,100), (2,350), ...]
如果您运行 hlint YourFile.hs,则会向您推荐这些重写。