-ãããŠãããªãã¯ã¿ãŒãã«ãã©ã€ã¯ããèŠãŸãããïŒ
ããããããšã¢ãªã¹ã¯èšã£ãã ãããã誰ãªã®ãããç¥ããŸãããã
ããŸãããšå¥³çã¯èšã£ãã -ããããã«ã¡ã®ã¹ãŒãã®ããã«ãäœãããŠãããã®ã§ãã
ã«ã€ã¹ã»ãã£ãã« ãäžæè°ã®åœã®ã¢ãªã¹ã
ãããªãã®ã¹ããŒãããå€æãããšããã¡ã³ãŽãŒã³ãããç¥ã£ãŠããŸããïŒã ã¢ã©ãŽã«ã³ã¯è¿äºãæ±ããã
-äœããããŸãïŒ -è人ã«çããã -ããã«ã¯100人ã®åœã ãã§ã¯ååã§ã¯ãããŸããã ããããæã ããã«è¡ããŸãã
ãžã§ã³R. R.ããŒã«ãã³ã ãããŒããªãã¶ãªã³ã°ã-Haskellã«ã€ããŠã®ç§ã®ç¥èã«ã€ããŠ
ãããã¹ãã ãã»ã³ãããã£ã¹ã³ãã ïŒä»ã®äººã«èª¬æ-ããªãã¯ç解ããŸããïŒ
ã©ãã³èªã®ããšãã
Haskellã®é¢æ°ã¯æ¬è³ªçã«1ã€ã®ãã©ã¡ãŒã¿ãŒã®é¢æ°ã§ããããšã¯èª°ããç¥ã£ãŠããŸãã ããã€ãã®ãã©ã¡ãŒã¿ã®ããã®ãŸãŸã®ãé¢æ°ã¯ãåã«æåã®åŒæ°ãåãå ¥ããïŒå ã®é¢æ°ã®ïŒ2çªç®ã®åŒæ°ãåããé¢æ°ãè¿ããªã©ã®å¥ã®é¢æ°ãè¿ããŸãã éé¢æ°åã®å€ãæ¢ã«è¿ããŠããæçµé¢æ°ïŒ currying ïŒãžã
ãã®ç¶æ³ã§è°è«ã§ãããã©ã¡ãŒã¿ãŒã®å¯å€æ°ã¯ã©ã®ããã«æããŸããïŒ ãã ãã printfã®ãœãŒã¹ã確èªããããwiki.haskellãèªãã ããããšã FPããã®åé¡ã«å¯Ÿãããããé£è§£ãªã解決çã§ã¯ãªããããªãçŸãã解決çãžã®éµãæäŸããŠããããšãæããã«ãªããŸãã
ãã®åºçç©ã§ã¯ãç°¡åãªäŸã䜿çšããŠãã®ãããªã¡ã«ããºã ãå®è£ ããæ¹æ³ã®1ã€ãæ€èšãã ãã³ãã¬ãŒãHaskellã«åºã¥ãäžè¬åããããœãªã¥ãŒã·ã§ã³ãææ¡ããŠããªã¹ãåã®æåŸã®ãã©ã¡ãŒã¿ãŒãæã€éåžžã®é¢æ°ã®ãã¡ããªãŒããããããå€æ°çªå·ãã©ã¡ãŒã¿ãŒãæã€ãé¢æ°ã«å€æããŸãïŒä»¥äžãããã¹ãã¯åã«ãå¯å€æ°ãã©ã¡ãŒã¿ãŒä»ããã§ãïŒã
éåžžã«ç°¡åãªäŸããå§ããŠããœãªã¥ãŒã·ã§ã³ã®æ¬è³ªãç°¡åã«èª¬æããŸãã
{-# LANGUAGE FlexibleInstances, RankNTypes #-} -- (0) class VarArgs a where prc :: String -> a -- (1) instance VarArgs String where prc = id -- (2) instance (Show a, VarArgs r) => VarArgs (a -> r) where -- (3) prc acc = \x -> prc $ acc ++ " " ++ show x magic = prc [] useMagic :: (forall a. VarArgs a => a) -> IO () -- (4) useMagic f = do putStrLn $ f 1 putStrLn $ f 1 "qwe" putStrLn $ f 1 "qwe" [1, 2, 3] main :: IO () main = do putStrLn $ magic 1 2 "qwe" [1,2,3] 123.456 useMagic magic -- (5)
ããã§äœãèµ·ãã£ãŠããŸããïŒãŸããä»»æã®æ°ã®ãã©ã¡ãŒã¿ãŒã ãã§ãªããç°ãªãã¿ã€ãã®ãã©ã¡ãŒã¿ãŒãããžãã¯é¢æ°ã«æž¡ãããšãã§ããŸããïŒ
ãããã£ãŠãïŒ1ïŒã§ã¯ãæååããç¹å®ã®åã®å€ãäœæããæ¹æ³ãåã«ç¥ã£ãŠããåäžã®prcã¡ãœããã§VarArgsã¯ã©ã¹ã宣èšããŸãã ããã«ãïŒ2ïŒã§ã¯ãStringåïŒ[Char]ãšãåŒã°ããïŒã®ãã®ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãå®è£ ããŸãã FlexibleInstancesïŒ0ïŒæ¡åŒµã䜿çšããå¿ èŠãããããšã«æ³šæããŠãã ãããããããªããšããã®ãããªã€ã³ã¹ã¿ã³ã¹ã¯ãéæ³ãã«ãªããŸãã
代æ¿ãœãªã¥ãŒã·ã§ã³ããããŸãããTypeFamiliesæ¡åŒµæ©èœãŸãã¯GADTã䜿çšããŸãã
{-# LANGUAGE TypeFamilies #-} instance a ~ Char => VarArgs [a] where prc = id
VarArgs Stringã€ã³ã¹ã¿ã³ã¹ã¯ãå®éã«ã¯å¯å€æ°ã®ãã©ã¡ãŒã¿ãŒãæã€é¢æ°ã®ãæ¬äœãã§ãã ãã®äŸã§ã¯ãåã«èç©ããããã©ã¡ãŒã¿ãŒãè¿ããŸãã ããã§æãèå³æ·±ãéšåã«ç§»ããŸããããïŒ3ïŒã§ã¯ãé¢æ°åïŒ a- > rïŒã®VarArgsã®ã€ã³ã¹ã¿ã³ã¹ã宣èšããŸãããåŒæ°åaãæååã«ãããã§ã ãçµæårãVarArgsã¯ã©ã¹ã«åã³å±ããããšãèŠæ±ããŸãã
ããã¯ããç¬ãé§ãæãããå Žæã§ããïŒç¹ã«ïŒé¢æ°ãèš±å¯ããæ»ãåãæã€é¢æ°åã§ã¯ã©ã¹ãã€ã³ã¹ã¿ã³ã¹åããããšã«ãããåŒã³åºãã®ã³ã³ããã¹ãã«å¿ããŠãã³ã³ããã¹ããæååãå¿ èŠãšããå Žåã æåååã®æçµå€ãšé¢æ°ã®äž¡æ¹ãè¿ãprcã¡ãœãããèš±å¯ããŸãprcåŒã³åºãã®çµæã®åã¯ãæ©èœçãšããŠã³ã³ããã¹ãããæšæž¬ãããŸãã
次ã«ã VarArgsïŒa-> rïŒã®ã€ã³ã¹ã¿ã³ã¹ã®prcå®çŸ©ãæ€èšããŸãã åprcãæšå®ãããšã次ã®ããã«ãªããŸã
prc :: (Show a, VarArgs r) => String -> (a -> r)
ã€ãŸã æååãšããŠè¡šãããå€ã§äœããããé¢æ°ãè¿ããªããã°ãªããŸããã accåŒæ°ã¯ããã©ã¡ãŒã¿ãŒã®é 次åŠçã®çµæã®ããã©ã€ããã®æ¬è³ªã§ãã ãã®å Žåããã©ã¡ãŒã¿ã®æååè¡šçŸãã¹ããŒã¹ã§è¿œå ããŸãã
éèŠãªç¹ã¯ãå¢åããããã¢ãã¥ã ã¬ãŒã¿ããè¿ãã ãã§ãªããïŒçµæã®é¢æ°ã®ãæ¬äœãã§ïŒ prcãååž°çã«åŒã³åºããŠãç®çã®çµæårãååŸããããšã§ãã ã©ã®prcå®è£ ãåŒã³åºããããïŒã€ãŸããã©ã®ã¿ã€ããæšè«ããããïŒã¯ã³ã³ããã¹ãã«äŸåããŸãïŒHaskellé¢æ°ã¯æ¹çšåŒã§ãããèšç®ããã»ã¹ã¯ãã©ã¡ãŒã¿ãŒãæŽæ°ããåŒã®é 次眮æã§ããããšãå¿ããªãã§ãã ããïŒã
æãèå³æ·±ãã®ã¯ããæºåæ³ãã¹ããŒã¿ã¹ã«ãããããããå¥ã®é¢æ°ã®åŒæ°ãšããŠå¯å€æ°ã®ãã©ã¡ãŒã¿ãŒãæã€é¢æ°ãæž¡ãïŒ4ïŒãšäœ¿çšããïŒ5ïŒããšã§ãã 確ãã«ããã®ããã«ã¯ãåŒã³åºãé¢æ°ã®å®çŸ©ïŒ4ïŒã§å¥ã®æ¡åŒµæ©èœRankNTypes ïŒ0ïŒãšforalléæå®åã䜿çšããå¿ èŠããããŸããã
å°ããããã«ããã®ã§ãïŒ4ïŒã®$ã®å³åŽã®åŒãã©ã®ããã«èšç®ãããããèŠãŠã¿ãŸãããã
- magicïŒaka prc [] ïŒã¯ãã©ã¡ãŒã¿ãŒ1ã§åŒã³åºãããŸãã æ©èœçãªã³ã³ããã¹ãã§äœ¿çšããããããã€ã³ã¹ã¿ã³ã¹ã¯æ©èœããŸã
VarArgsïŒa-> rïŒ ãæçµçã«è¿ããã... - ...åã³æ©èœãã ããã§ãåŒæ°2ããããŸãã æ©èœã³ã³ããã¹ã
- ãqweããš[1,2,3]ã¯åæ§ã«åŠçãããŸã
- æåŸã«ã以åã®ãã©ã¡ãŒã¿ãŒãšçŸåšã®ãã©ã¡ãŒã¿ãŒ123.456ã®èç©ãããæååè¡šçŸãæã€prcé¢æ°ã®æåŸã®åŒã³åºãã®çµæã¯ã putStrLné¢æ°ã®ãã©ã¡ãŒã¿ãŒã®ãããªæååã³ã³ããã¹ããæ¢ã«å¿ èŠãšããŸã-prcã¯VarArgs Stringã€ã³ã¹ã¿ã³ã¹ããèµ·åãããŸã
次ã«ãããå°ãããè€éãªäŸãèããŠã¿ãŸãããã éããŒã©ã³ãèšæ³ã®åŒèšç®æ©ã§ãã 次ã®ãããªãã®ïŒ
> calcRPN 5 8 (*) 2 (+) -- 5*8 + 2 42
æãåå§çãªå®è£ ã¯æ¬¡ã®ããã«ãªããŸãã
{-# LANGUAGE ExtendedDefaultRules, FlexibleInstances, GADTs #-} data Expr = Num Double | Op (Double -> Double -> Double) calcRPN' :: [Expr] -> Double calcRPN' = head . foldr rpnStep [] . reverse rpnStep :: Expr -> [Double] -> [Double] rpnStep (Num n) stack = n : stack rpnStep (Op f) (x:y:stack) = (fxy) : stack class ArgPrc a where prc :: [Expr] -> a class ArgSrc a where toArg :: a -> Expr instance ArgPrc Double where prc = calcRPN' . reverse instance (ArgSrc a, ArgPrc r) => ArgPrc (a -> r) where prc acc = prc . (: acc) . toArg -- (2) instance ArgSrc Expr where toArg = id instance a ~ Double => ArgSrc (a -> a -> a) where toArg = Op instance ArgSrc Integer where toArg = Num . fromIntegral instance ArgSrc String where toArg = Num . fst . head . (reads :: ReadS Double) instance ArgSrc [Double] where toArg = Num . sum calcRPN :: ArgPrc a => a calcRPN = prc [] main = do print $ calcRPN' [Num 5, Num 5, Op (*)] print $ calcRPN [1::Double,2,3] "5" (*) 7 (*)
å¯å€æ°ã®ãã©ã¡ãŒã¿ãŒãå®è£ ããããã®ã¹ããŒã ã¯åã®äŸãšåãã§ãããããã§ã®ã¿ïŒ
- çµæãããã«æ§ç¯ããã®ã§ã¯ãªããåŸç¶ã®åŠçã®ããã«ïŒ Expråã®ïŒåŒæ°ããªã¹ãã«èç©ããŸãïŒ2ïŒã
- ãã©ãããŒãã¯ã©ã¹ArgSrcã䜿çšããŠããåŒããšããŠæ©èœã§ããåã宣èšããŸãïŒ Expr ïŒ
- ããã€ãã®ãããªãã¯ãïŒGADTæ¡åŒµæ©èœïŒã䜿çšããŠã€ã³ã¹ã¿ã³ã¹ãå®è£
ãã
ã€ã³ã¹ã¿ã³ã¹aãDouble => ArgSrcïŒa-> a-> aïŒ
æåŸã«ãprintfé¢æ°ã®åè·¯å³å®è£ ãèŠãŠã¿ãŸãããã
{-# LANGUAGE GADTs, FlexibleInstances, ExtendedDefaultRules #-} type FmtRes = (String, String) class PfVal a where doFmt :: (String, String) -> a -> FmtRes instance PfVal Integer where doFmt (fmt, res) x = let (b, s) = span (/= '%') fmt in (res ++ (tail . tail $ s), b ++ show x) instance PfVal String where doFmt (fmt, res) x = let (b, s) = span (/= '%') fmt in (res ++ (tail . tail $ s), b ++ x) class ArgProc a where prc :: FmtRes -> a instance ArgProc String where prc = uncurry (++) instance ArgProc (IO ()) where prc = putStrLn . uncurry (++) instance (PfVal a, ArgProc r) => ArgProc (a -> r) where prc st = prc . doFmt st printf fmt = prc (fmt, "") main :: IO() main = do putStrLn $ printf "%d %s" 1 "qwe" printf "%s %d" "This is" 123
ã³ãŒãã«ç¹å¥ãªã³ã¡ã³ãã¯å¿ èŠãªããšæããŸãããã©ã¡ãŒã¿ãŒãèç©ãã代ããã«ãçµæãããªã³ã¶ãã©ã€ãã§åã³çæãã ArgProcã¯ã©ã¹ã®2ã€ã®ã¿ãŒããã«ã€ã³ã¹ã¿ã³ã¹ãå®è£ ããããšã«æ³šæããŠãã ãã ïŒ StringåãšIOïŒïŒå ã
å³ã®ã¹ããŒã ãäžè¬åãããšã次ã®èŠçŽ ãåºå¥ã§ããŸãã
- ããã€ãã®ã¿ã€ãã¯ããããªãŒã§ãïŒ AãåŒã³åºããŸãããïŒãã¿ã€ãaã®ãã©ã¡ãŒã¿ãŒã«åºã¥ããäºåèšç®çµæã§ãã ãäºåãã®çšåºŠã¯ããªã¹ãã¿ã€ãã®ã³ã³ããå
ã®ãã©ã¡ãŒã¿ã®åçŽãªçŽ¯ç©ïŒ éããŒã©ã³ãè¡šèšã®äŸã®ããã«ïŒãããçŸåšã®ãã©ã¡ãŒã¿ã»ããã®ã»ãŒæºåå®äºã®çµæïŒ printfã®äŸã®ããã«ïŒãŸã§å€åããŸãã ãã®ã¿ã€ãããå¿
èŠãªã®ã¯ãã¿ã€ãã®ãªãã¬ãŒã·ã§ã³ã®ååšã ãã§ã
A -> a -> A
- ã¡ã€ã³ã¯ã©ã¹ïŒ ArgProcãåŒã³åºããŸãããïŒãã€ã³ã¹ã¿ã³ã¹ãéããŠãå¯å€æ°ã®ãã©ã¡ãŒã¿ãŒã®ãã¹ãŠã®ãã¡ã«ãã¯ã¹ããå®è£
ãããŸãã ãã®ã¯ã©ã¹ã«ã¯ãããããªãŒAã§äœããè¡ã1ã€ã®ã¡ãœããïŒ prcãåŒã³åºããŸãããïŒããããŸãã
class ArgProc a where prc :: A -> a
- å€ããã©ã¡ãŒã¿ãŒåã«å€æããæ©èœããµããŒããããã©ã¡ãŒã¿ãŒãšããŠæ©èœã§ããã¿ã€ãã®ã¯ã©ã¹ïŒ ArgSrcãåŒã³åºããŸãããïŒïŒäžéšã®ã¿ã€ãaã¯æäœ:: A-> a- > Aãèš±å¯ããŸãïŒ
- ãã©ã¡ãŒã¿ãŒã®åŠçãšäºåçµæã®èç©ãè¡ãã¡ã€ã³ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ïŒ
instance (ArgSrc a, ArgProc r) ArgProc (a -> r) where prc :: A -> (a -> r)
printfã䜿çšããäŸã§ã¯ãçµæã¯ããã«çŽ¯ç©ããïŒãã¢ã®2çªç®ã®èŠçŽ ïŒãç¶æ ã¯éäžã§åŠçãããŸãïŒãã©ãŒãããæååïŒã éããŒã©ã³ãèšæ³ã䜿çšããäŸã§ã¯ããã©ã¡ãŒã¿ã¯ãªã¹ãã«è¿œå ãããããã«åŠçãããŸãã
- äºåçµæã®æçµåŠçãæ
åœããã¡ã€ã³ã¯ã©ã¹ã®ã¿ãŒããã«ã€ã³ã¹ã¿ã³ã¹ïŒ
instance ArgProc R1 where prc :: A -> R1 instance ArgProc R2 where prc :: A -> R2 ...
éããŒã©ã³ãè¡šèšæ³ã®äŸã§ã¯ãçµæã®Doubleåã«å¯ŸããŠãã®ãããªã€ã³ã¹ã¿ã³ã¹ã1ã€ã ããããŸãã以åã«èç©ããããã©ã¡ãŒã¿ãŒã®ãªã¹ãã®èšç®ãéå§ããã ãã§ãã printfã®äŸã§ã¯ãStringã®ã€ã³ã¹ã¿ã³ã¹ã¯ããã©ãŒããããããæååãšæ®ãã®ãã©ãŒããããåçŽã«é£çµããŸãïŒããã«ã¯ãã©ããããã¹ããæ®ã£ãŠãããšæ³å®ãããŸãïŒã IOïŒïŒã®ã€ã³ã¹ã¿ã³ã¹ã¯ããã«çµæã衚瀺ããŸãã
- äºåèšç®çµæAã®åæç¶æ
ã®åæååã¯ãäžè¬çãªå Žåãåºå®ãã©ã¡ãŒã¿ãŒã®ã»ããã®é¢æ°ã§ãããäŸã§ã¯ãå®æ°å€[]ããã³é¢æ°ã§ãã
\x -> (x, "") :: String -> (String -> String)
ãã®ãããªã¹ããŒã ã¯ãããã©ãã¯ããžãã¯ã ãã³ãã¬ãŒãHaskellã®æ段ã䜿çšããŠå®è£ ã§ããããšãããããŸãã ããã¯ãçŽ æãçµ±åããã®ã«é©ããæŒç¿ã§ããã ãã³ãã¬ãŒãHaskellãè©ŠããŠ
çŸåšã®å®è£ ã§ã¯ãç§ã¯èªåèªèº«ãäžè¬çãªã¹ããŒã ã®ãµãã»ããã«éå®ããŸããããã©ã€ãã¯ããã¿ã€ãã®å€ã®ãªã¹ãã«éãããåæååã¯ããã«å¿ããŠåçŽã§ã[] ã ãã®ãããªå¶éã«ã¯ç¢ºãã«äžå©ãªç¹ããããŸãããã¢ã€ãã¢ã¯ãåãã¿ã€ãã®ãã©ã¡ãŒã¿ãŒãæã€æåŸã®ãªã¹ããšããŸããŸãªæ»ãå€ã¿ã€ããæã€éåžžã®é¢æ°ã®ãã¡ããªãŒããå¯å€æ°ã®ãã©ã¡ãŒã¿ãŒïŒãªã¹ãã«ç§»åããåºå®ãã©ã¡ãŒã¿ãŒã«å ããŠïŒãåãé¢æ°ã«å€æããããšã§ãã
éäžã§ãæå®ãããåãããã©ã¡ãŒã¿ãŒãªã¹ãã®èŠçŽ ã®åãžã®ãæé»çãªãã£ã¹ããïŒä»ã®PLã®çšèªã§ã¯ïŒã®ããã»ã¹ãèªååããŸãã ãã1ã€ã®å¶éã¯ãããããŒãé¢æ°ã«ã¯ãåçŽãªãåïŒéæå®åãšå¶éã®ãªãéå€ååïŒãå¿ èŠã§ããããšã§ãã
ç¹°ãè¿ãã«ãªããŸãããããã«äœ¿çšäŸããå§ããŸãã®ã§ãã¢ã€ãã¢ã¯æ確ã«ãªããŸããããããåããŠå®è£ ãç°¡åã«èª¬æããŸãã ããã§ã¯ãç°¡åãªãã®ããå§ããŸãããã
{-# LANGUAGE TemplateHaskell, FlexibleInstances, ExtendedDefaultRules #-} import Data.Function.Vargs -- (1) -- (2) tester' q (x : y : z) = putStrLn $ "Fixed parameter " ++ q ++ ", next x = " ++ x ++ " and y = " ++ y ++ " and rest = " ++ show z $( return [] ) -- (3) -- (4) defVargsFun "tester" ['tester'] (''Integer, [| ("Int " ++) . show |]) -- (5) (''(), [| const "NULL" |]) -- (6) ([t| [Int] |], [| ("[Int] " ++) . show |]) -- (7) ([t| [Double] |], [| ("[Double] " ++) . show |]) -- (8) main :: IO () main = do tester "<const>" "qwe" 100500 () [1::Int,2,3] [4::Double,5,6] -- (9)
ãã®äŸã§ã¯ã次ã®åã®ãã¹ã¿ãŒé¢æ°ã®ãã¹ã¿ãŒã©ãããŒé¢æ°ãäœæããŸãã
tester' :: String -> [String] -> IO ()
ããã¹ããèŠãŠãããŸãããã
- ïŒ1ïŒ-å¯å€æ°ã®ãã©ã¡ãŒã¿ãŒãå®è£ ããã¢ãžã¥ãŒã«ãæ¥ç¶ããŸã
- ïŒ2ïŒ-å€æã®ããã®ãå®éšçãæ©èœãå®çŸ©ããŸã
- ïŒ3ïŒ -Reifyæäœãä¿èšŒããããã®ããªãã¯ïŒè©³çŽ°ã«ã€ããŠã¯ãããšãã°ã ãã¡ã ïŒ
- ïŒ4ïŒ-å¯å€æ°ã®ãã©ã¡ãŒã¿ãŒã䜿çšããŠé¢æ°ãå®çŸ©ãã
3çªç®ããå§ãŸããã©ã¡ãŒã¿ãŒ-ããããã®ã¿ã€ãã®å€ïŒ
- ïŒååãExpQïŒ
- ïŒTypeQãExpQïŒ
ãããã¯ãæå®ãããã¿ã€ãïŒæŽæ°ãïŒïŒãªã©ïŒã®å€ããã©ã¡ãŒã¿ãŒãªã¹ãå ã®èŠçŽ ã®ã¿ã€ãïŒStringïŒã®å€ã«å€æããæ¹æ³ã説æããŠããŸãã ã¿ã€ãã¯ãååïŒïŒ5ïŒãïŒ6ïŒïŒãŸãã¯åŒïŒïŒ7ïŒãïŒ8ïŒïŒã®ããããã§æå®ãããŸãã èŠçŽ èªäœãå€æ°ãã©ã¡ãŒã¿ãŒãšããŠæž¡ãããããšã«æ³šæããŠãã ããïŒ
- ïŒ9ïŒ-ä»»æã®é åºã§ã®ããŸããŸãªã¿ã€ãã®å¯å€æ°ã®ãã©ã¡ãŒã¿ãŒïŒã¹ããªã³ã°ã«çž®å°å¯èœïŒã䜿çšããå®éã®é¢æ°åŒã³åºã
ããã«é²ãããéããŒã©ã³ãèšæ³ã䜿çšããŠäŸã«æ»ããŸãã
{-# LANGUAGE TemplateHaskell, FlexibleInstances, ExtendedDefaultRules, GADTs #-} -- import Data.Function.Vargs data Expr = Num Double | Op (Double -> Double -> Double) calcRPN' :: [Expr] -> Double calcRPN' = head . foldr rpnStep [] . reverse rpnStep :: Expr -> [Double] -> [Double] rpnStep (Num n) stack = n : stack rpnStep (Op f) (x:y:stack) = (fxy) : stack $( return [] ) defVargsFun "calcRPN" ['calcRPN'] (''Integer, [| Num . fromIntegral |]) (''String, [| Num . fst . head . (reads :: ReadS Double) |]) (Genz [t| Double -> Double -> Double |], [| Op |]) -- (1) ([t| [Double] |], [| Num . sum |]) main = do print $ calcRPN' [Num 5, Num 5, Op (*)] print $ calcRPN [1::Double,2,3] "5" (+) 7 (*)
ãã®äŸã§ã¯ã1ã€èå³æ·±ãç¹ïŒ1ïŒãé€ããŠããã¹ãŠãåã®äŸãšäŒŒãŠããŸããããã§ã¯ãTypeQã ãã§ãªããGenQã©ãããŒã䜿çšããŠããŸãã ãã®ã©ãããŒã¯ããžã§ãã¬ãŒã¿ãŒã«æ¬¡ã®åœ¢åŒã®ã€ã³ã¹ã¿ã³ã¹ãäœæãããŸãã
instance a ~ Double => ArgSrc (a -> a -> a) where
æšæºã®ä»£ããã«
instance ArgSrc (Double -> Double -> Double) where
ãã®å Žåãåãã§ãã¯ã«åæ ŒããŸããã
ããŠãæåŸã®äŸã¯ãåãprintfé¢æ°ããŸãã¯ãããšé¡äŒŒããåè·¯å³ã§ãïŒ
{-# LANGUAGE TemplateHaskell, FlexibleInstances, ExtendedDefaultRules, ExistentialQuantification #-} import Data.Function.Vargs type FmtRes = (String, String) class PfVal a where doFmt :: FmtRes -> a -> FmtRes instance PfVal Integer where doFmt (fmt, res) x = let (b, s) = span (/= '%') fmt in (res ++ (tail . tail $ s), b ++ show x) instance PfVal Double where doFmt (fmt, res) x = let (b, s) = span (/= '%') fmt in (res ++ (tail . tail $ s), b ++ show x) instance PfVal String where doFmt (fmt, res) x = let (b, s) = span (/= '%') fmt in (res ++ (tail . tail $ s), b ++ x) data PfValWrap = forall a. PfVal a => Val a -- (1) printf_String :: String -> [PfValWrap] -> String -- (2) printf_String fmt vs = uncurry (flip (++)) $ foldl step (fmt, "") vs where step fmt (Val f) = doFmt fmt f printf_IO :: String -> [PfValWrap] -> IO () -- (3) printf_IO fmt = putStrLn . printf_String fmt $( return [] ) defVargsFun "printf" ['printf_String, 'printf_IO] -- (4) [''Integer, ''Double, ''String] main :: IO () main = do let fmt = "Number one is %d, number two is %f and string is \"%s\"" printf_IO fmt [Val 100, Val 123.456, Val "ok"] putStrLn $ printf fmt 100 123.456 "ok" printf fmt 100 123.456 "ok"
泚ç®ã«å€ãã3ã€ã®æ°ãããã€ã³ãããããŸãã
- ã©ãããŒã¿ã€ãïŒ1ïŒã䜿çšããŠã PfValã¯ã©ã¹ã®ã³ã³ãã©ã¯ãããµããŒãããä»»æã®ã¿ã€ãã®å€ãåŠçããïŒæå®ããã圢åŒã§æååã«åºåã§ããïŒ
- 2ã€ã®ãã©ã¡ãŒã¿ãŒãã³ãã©ãŒã®ååšïŒ2ïŒ-ïŒ3ïŒç°ãªãã¿ã€ãã®çµæïŒ Stringããã³IOïŒïŒ ïŒ
- æå®ãããåã®å€ãPfValWrapã©ãããŒåã«å€æããããã®èªåã³ãŒãçæïŒå®éãå¯äžã®åã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãªãã¬ã¯ã·ã§ã³reifyãä»ããŠãã«ãããŸã-Val ïŒ
ããã§ãããããã¹ãŠã©ã®ããã«æ©èœãããã«ã€ããŠã®ããã€ãã®èšè å®éã defVargsFunãè¡ãããšã¯ã reifyããåãåã£ãæ å ±ãšãå¯å€æ°ã®ãã©ã¡ãŒã¿ãŒãæã€é¢æ°èªäœã®å®£èšãšå®çŸ©ã«åºã¥ããŠãããã€ãã®ã¯ã©ã¹ãšã€ã³ã¹ã¿ã³ã¹ãäœæããããšã ãã§ãã ãã®ããããã³ãã¯ãã¹ãŠã以åã«äŸã§æ€èšãããäžè¬çãªã¹ããŒã ã«å¯Ÿå¿ããŠããŸãã ç¹°ãè¿ããŸãããæ£ç¢ºã«çæããããã®ãäŸã§ç€ºãããšã¯ãããæ確ã§ç°¡åã§ãã åŒã³åºãã«ãã£ãŠçæãããã³ãŒããæ€èšããŠãã ããã
defVargsFun "printf" ['printf_String, 'printf_IO] [''Integer, ''Double, ''String]
-ddump-splicesã¹ã€ããã䜿çšããŠghcãå®è¡ãããšããã®ã³ãŒãã衚瀺ãããŸãã æ確ã«ããããã«ããã©ãŒããããä¿®æ£ããäœåãªæ¬åŒ§ãåé€ããŸããã
class ArgPrc_printf_aa3M a where -- (1) prc_printf_aa3O :: String -> [PfValWrap] -> a -- (2) class ArgSrc_printf_aa3N a where -- (3) toArg_printf_aa3Q :: a -> PfValWrap -- (4) instance ArgPrc_printf_aa3M String where -- (5) prc_printf_aa3O a1 = printf_String a1 . reverse instance ArgPrc_printf_aa3M (IO ()) where -- (6) prc_printf_aa3O a1 = printf_IO a1 . reverse -- (7) instance (ArgSrc_printf_aa3N a, ArgPrc_printf_aa3M r) => ArgPrc_printf_aa3M (a -> r) where prc_printf_aa3O a1 acc_printf_aa3P = prc_printf_aa3O a1 . (: acc_printf_aa3P) . toArg_printf_aa3Q -- (8) instance ArgSrc_printf_aa3N PfValWrap where toArg_printf_aa3Q = id instance ArgSrc_printf_aa3N Integer where toArg_printf_aa3Q = Val instance ArgSrc_printf_aa3N Double where toArg_printf_aa3Q = Val instance ArgSrc_printf_aa3N String where toArg_printf_aa3Q = Val -- (9) printf :: forall a. ArgPrc_printf_aa3M a => String -> a printf a1 = prc_printf_aa3O a1 []
Monad Qã¯ããŠããŒã¯ãªååã®çæãæäŸããŸã-ãã®ãããååã®ããã£ãããŒãªããšã³ãã£ã³ã°ã§ãã ããã¹ããèŠãŠãããŸãããã
- å¯å€æ°ã®ãã©ã¡ãŒã¿ãŒã®ã¡ã€ã³ããã»ããµã¯ã©ã¹ïŒ1ïŒãšãã®ããŒã¡ãœããïŒ2ïŒã宣èšãããŠãã
- ã¯ã©ã¹ïŒ3ïŒã¯ãåäžã®ã¡ãœããïŒ4ïŒã䜿çšããŠãæå®ãããåã®å€ããã©ã¡ãŒã¿ãŒãªã¹ãïŒ PfValWrap ïŒã®èŠçŽ ã®åã«ãæé»çã«å€æãããããã«å®£èšãããŸã
- ã¡ã€ã³ã¯ã©ã¹ïŒ1ïŒã®ãã¿ãŒããã«ãã€ã³ã¹ã¿ã³ã¹ã¯ãStringïŒ5ïŒããã³IOïŒïŒïŒ6ïŒã¿ã€ãã«å¯ŸããŠå®çŸ©ãããŸããã¡ãœããã®å®è£ ã¯ããã¹ãŠã®åºå®ãã©ã¡ãŒã¿ãŒãšèç©ããããå€æ°ããã©ã¡ãŒã¿ãŒã®ãªã¹ããæå®ããé¢æ°ã®åŒã³åºãã§ãã ãªããªã ãã©ã¡ãŒã¿ã®èç©ã¯ãªã¹ãã®ãå é ãããå®è¡ãããããã€ãã£ããé¢æ°ãåŒã³åºãåã«ã ãªããŒã¹ãåŒã³åºãããŸã
- ã¡ã€ã³ã¯ã©ã¹ïŒ1ïŒã®ã€ã³ã¹ã¿ã³ã¹ïŒ7ïŒã¯æ©èœã¿ã€ãïŒ a- > rïŒã§æ±ºå®ãããŸã-ããã§ã¯ãç¹å¥ã«äœæãããã¯ã©ã¹ïŒ3ïŒã«å±ããã¿ã€ãã®å€ã¯ãã¡ãœããïŒ4ïŒããã©ã¡ãŒã¿ãŒãªã¹ãèŠçŽ ã®ã¿ã€ãïŒ PfValWrap ïŒã«åŒã³åºãããšã§å€æãããŸãããããŠãã®å€ããªã¹ãã«å ¥ãã
- ããã«ïŒ8ïŒãã¯ã©ã¹ïŒ3ïŒã®ã€ã³ã¹ã¿ã³ã¹ã¯ã瀺ããããã¹ãŠã®å+ PfValWrapåèªäœã®ã€ã³ã¹ã¿ã³ã¹ã«å¯ŸããŠæ±ºå®ãããŸãïŒå€æã«ã¯ã¡ãœããïŒ4ïŒãåŒã³åºãããããããããŒãããžãŒããå¿ èŠã§ãïŒ
- ãããŠæåŸã«ãã©ãããŒé¢æ°èªäœãå¯å€æ°ã®ãã©ã¡ãŒã¿ãŒã§å®£èšããã³å®çŸ©ãããŸã
ã³ã¡ã³ãä»ãã®Data.Function.Vargsã¢ãžã¥ãŒã«ã®ãœãŒã¹ã³ãŒããšãã®äœ¿çšäŸã¯ããã«ãããŸã; haddoc圢åŒã®ããã¥ã¡ã³ãã¯ãããšããã±ãŒãžã®äžéšãšããŠå ¥æã§ããŸãã çŸæç¹ã§ã¯ãããã±ãŒãžã¯ãå®å šããšããèšèããå®éšæ®µéã«ãããŸã;ïŒ
ãããããæéã®çµéãšãšãã«ãããæãèµ·ããããŸã-å°ãªããšãããšã©ãŒç¶æ ïŒç¡å¹ãŸãã¯äºææ§ã®ãªãã¿ã€ãïŒãæ倧ã§åæããã³åŠçããå¿ èŠããããŸãã
- äžè¬åãããã¹ããŒã ãå®è£ ããã芪ãé¢æ°ã§å€æ åããµããŒãããŸãã
- ç¹ã«ãã©ããã³ã°é¢æ°ããã©ã¡ãŒã¿ãŒãšããŠä»ã®é¢æ°ã«æž¡ãå¯èœæ§ã®ããã«ãäœæãããã¯ã©ã¹ããã³ã¡ãœããã«æå³ã®ããååãä»ããŸãã
- 代æ¿ã®å®è£ ã¹ããŒã ãæ€èšããããšã¯å¯èœã§ãã
ãããã¯ã«é¢ãã圹ç«ã€ãªã³ã¯ïŒ