无点形式与风格

时间:2010-11-21 00:16:14

标签: haskell coding-style pointfree

你能转换吗

-- tupleUnfold :: forall a. ((forall b. a -> b)) -> a -> ((b))
tupleUnfold :: Int -> ExpQ
tupleUnfold n = do
  xs <- forM [1 .. n] (const . newName $ "x")
  y <- newName "y"
  let y' = varE y
      g (ps', es') x = (varP x : ps', appE (varE x) y' : es')
      (ps, es) = foldl' g ([], []) xs
  lamE [tupP ps, varP y] (tupE es)

以自由的方式保持清晰(我知道程序'pointfree',但更愿意不再混淆代码)?

无论哪种方式,可以做出哪些改变来改进功能的风格,或者使其意图更清晰?该功能旨在如下使用。

$(tupleUnfold 3) ((+ 1), (+ 2), (+ 3)) 2
-- (3, 4, 5)

要使用哪些更好的命名约定(请参阅ps,ps',es和es'变量)?

3 个答案:

答案 0 :(得分:5)

这就是我得到的。需要Control.Arrow (&&&)Control.Applicative (<$>)

tupleUnfold :: Int -> ExpQ
tupleUnfold n = do
    y <- newName "y"
    (ps,es) <- unzip . map (varP &&& (`appE` varE y) . varE) 
                <$> replicateM n (newName "x")
    lamE [tupP ps, varP y] (tupE es)

如果不让它完全不可理解,就不能贬低它。

编辑虽然不是免费的,但这里是最清晰的我能做到的。需要Data.Function (on)

tupleUnfold :: Int -> ExpQ
tupleUnfold n = do
    y <- newName "y"
    xs <- replicateM n (newName "x")
    let exps = tupE $ zipWith appVars xs (repeat y)
        pats = tupP $ map varP xs
    lamE [pats, varP y] exps
  where
    appVars = appE `on` varE

答案 1 :(得分:1)

更难以理解(尝试从右到左阅读):

tupleUnfold n = do
  y <- newName "y"
  uncurry lamE . ((:[varP y]) . tupP *** tupE) . unzip .   
   map (varP &&& (`appE` varE y) . varE) <$> replicateM n (newName "x")

修改
用于处理的箭头和功能组合的混合

tupleUnfold n = do
  y <- newName "y"
  uncurry lamE . ((tupP >>> (:[varP y])) *** tupE) . unzip .
    map (varP &&& (varE >>> (`appE` varE y))) <$> replicateM n (newName "x")

主要使用箭头(从左到右读取处理功能)

tupleUnfold n = do
  y <- newName "y"
  (map (varP &&& (varE >>> (`appE` varE y))) >>> unzip >>>
    ((tupP >>> (:[varP y])) *** tupE) >>> uncurry lamE) <$> replicateM n (newName "x")

请注意,箭头功能(&gt;&gt;&gt;)相当于翻转(。)

答案 2 :(得分:0)

就我个人而言,我认为已经非常清楚了,但是这个怎么样:

tupleUnfold :: Int -> ExpQ
tupleUnfold = mapM (const . newName $ "x") . enumFromTo 1 >=> \xs -> do
    y <- newName "y"
    let y' = varE y
        g (ps', es') x = (varP x : ps', appE (varE x) y' : es')
        f ps = lamE [tupP ps, varP y] . tupE
    uncurry f $ foldl' g ([],[]) xs

Kleisli组合运算符>=>(来自Control.Monad)对于创建无点monadic函数非常有用。