関数引数のpermutation (3)
今度は [a b c, a c b, ...] に \a b c -> f をmapするというとてもマクロ的な作戦。
x <- newName str
で作った変数はschemeのマクロのように変数の衝突を回避するけれど、
mkName str
で作った変数は文字どおりstrのままでダイナミックスコープ。
permArgs' :: Int -> ExpQ permArgs' n = [| \f -> $( do -- 変数(a, b, c..)の生成 nms <- sequence $ replicate n $ newName "x" listE $ -- \[a, b, c] -> (\a b c -> f a b c) map (\vars -> lamE (map varP nms) (appsE (varE (mkName "f"):vars))) -- [a, b, c] -> [[a, b, c], [a, c, b],...] $ [ map varE nms' | nms' <- perm nms ] ) |] appsE :: [ExpQ] -> ExpQ appsE = foldl1 appE perm [] = [[]] perm xs = [(y:ys) | y <- xs, ys <- perm $ delete y xs]