そんなんできるのか、と思ってたけど分かってしまえば簡単…なのか?
import Numeric (showHex) type Format a b = (String -> a) -> String -> b format :: Format String a -> a format f = f id "" q :: String -> Format a a q x = q' where q' k s = k (s ++ x) str :: Format a (String -> a) str k s x = k (s ++ x) int :: Format a (Int -> a) int k s n = k (s ++ show n) hex :: Format a (Int -> a) hex k s n = k (s ++ showHex n "") (&) :: Format b c -> Format a b -> Format a c f & f' = f'' where f'' k s = f (\s' -> f' k s') s
こんな風に。
main = do putStr "name: " name <- getLine putStr "num: " num <- readLn putStrLn $ format (q"Hello, " & str & q"! " & int & q" = 0x" & hex) name num num
さらに
(%) = (&) s = str d = int x = hex (!) = flip (flip (%) . q)
とすれば
putStrLn $ format (q"Hello, " %s !"! " %d !" = 0x" %x) name num num
とできてprintfっぽい(かも)。
文字列にq
を適用するのが面倒なので(リテラルはそのままでフォーマッタになってほしい)
{-# OPTIONS_GHC -fglasgow-exts #-} -- ... class ToF a where toF :: a -> Format b c instance ToF String where toF = q instance ToF (Format a b) where toF = id
としたかったんだけどエラーが出るなあ。(toF
のa,b,c
に依存が出てしまうのが問題?よくわからない)