Scrap Your Boilerplate ことはじめ2
昨日のやつのモナド版を作ってみます。
recMapM :: forall a b m. (Data a, Data b, Monad m) => (b -> m b) -> a -> m a recMapM f x = do let recurse = gmapM (recMapM f) x case cast x of Nothing -> recurse Just bx -> do z <- f bx case cast z of Nothing -> recurse Just az -> return az
途中Maybe (m (Maybe b))という型になるため、Maybeを手で扱う必要が出てくる必要があっていやーんな感じです。何とかならないものでしょうか。二つのMaybeの文脈は結合したいし、かといってmがMonadMaybeであることを要求したくはないわけで。
ともかくこれがあればモナド無双できます。倍精度実数の部分にちょっとだけ乱数を足すとか。
ghci> recMapM (\x -> getRandomR (x,(1.01::Double)*x)) a1 >>= print Abc (Bca (Cab (A "Happy") (B 4.215734581306111)) (Abc (B 5.627533165698871) (C 512))) (Cab (Abc (B 8.482016322000884) (C 208)) (Bca (C 2012) (A "New Year!")))
文字列パートを強調する方法をすべて列挙するとか。
ghci> mapM_ print $ recMapM (\str -> [str, "Very " ++ str, "Extremely " ++ str]) a1 Abc (Bca (Cab (A "Happy") (B 4.2)) (Abc (B 5.6) (C 512))) (Cab (Abc (B 8.4) (C 208)) (Bca (C 2012) (A "New Year!"))) Abc (Bca (Cab (A "Happy") (B 4.2)) (Abc (B 5.6) (C 512))) (Cab (Abc (B 8.4) (C 208)) (Bca (C 2012) (A "Very New Year!"))) Abc (Bca (Cab (A "Happy") (B 4.2)) (Abc (B 5.6) (C 512))) (Cab (Abc (B 8.4) (C 208)) (Bca (C 2012) (A "Extremely New Year!"))) Abc (Bca (Cab (A "Very Happy") (B 4.2)) (Abc (B 5.6) (C 512))) (Cab (Abc (B 8.4) (C 208)) (Bca (C 2012) (A "New Year!"))) Abc (Bca (Cab (A "Very Happy") (B 4.2)) (Abc (B 5.6) (C 512))) (Cab (Abc (B 8.4) (C 208)) (Bca (C 2012) (A "Very New Year!"))) Abc (Bca (Cab (A "Very Happy") (B 4.2)) (Abc (B 5.6) (C 512))) (Cab (Abc (B 8.4) (C 208)) (Bca (C 2012) (A "Extremely New Year!"))) Abc (Bca (Cab (A "Extremely Happy") (B 4.2)) (Abc (B 5.6) (C 512))) (Cab (Abc (B 8.4) (C 208)) (Bca (C 2012) (A "New Year!"))) Abc (Bca (Cab (A "Extremely Happy") (B 4.2)) (Abc (B 5.6) (C 512))) (Cab (Abc (B 8.4) (C 208)) (Bca (C 2012) (A "Very New Year!"))) Abc (Bca (Cab (A "Extremely Happy") (B 4.2)) (Abc (B 5.6) (C 512))) (Cab (Abc (B 8.4) (C 208)) (Bca (C 2012) (A "Extremely New Year!")))