Бессмысленная форма против стиля - PullRequest
6 голосов
/ 21 ноября 2010

Можете ли вы преобразовать

-- 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, сохраняя ясность (я знаю о программе 'pointfree', но предпочел бы не запутывать код еще больше)?

ЛибоКстати, какие изменения можно было бы внести, чтобы улучшить стиль функции, или иным образом прояснить ее намерения?Функция предназначена для использования, как показано ниже.

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

Какие лучше использовать соглашения об именах (см. Переменные ps, ps ', es и es')?

Ответы [ 3 ]

5 голосов
/ 21 ноября 2010

Вот что я получил. Необходимо 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)

Невозможно сделать гораздо больше, не сделав его совершенно непонятным.

РЕДАКТИРОВАТЬ Хотя это не точка бесплатно, вот самый ясный 1011 * Я мог бы сделать это Необходимо 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 голос
/ 22 ноября 2010

чуть более непонятно (попробуйте прочитать справа налево):

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")

обратите внимание, что функция стрелки (>>>) эквивалентна flip (.)

0 голосов
/ 21 ноября 2010

Лично я думаю, что это уже достаточно ясно, но как насчет этого:

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) полезен для создания бессмысленных монадических функций.

...