Инкапсуляция списка функций в haskell в один - PullRequest
6 голосов
/ 03 декабря 2010

Кто-то сказал, что я, возможно, не «понимаю», как правильно писать код на Haskell.Кто-то должен быть абсолютно прав, поскольку я чувствую весь мой код на haskell, но более простые функции действительно ужасны (по крайней мере, по сравнению с моим кодом ООП на «стандартном» языке, таком как Java или C ++):

mev = matrixExpValues 5 4 3
cs = canonicalSt 4 3

cs_t1 = map (foldl (++) "") (map (map show) cs)
cs_t2 = map (++ ":") cs_t1
mev_t1 = intXxsToStringXxs mev
mev_t2 = map (map (++ "\t")) mev_t1
mev_t3 = map (foldl (++) "") mev_t2
res1 = zipWith (++) (map (++ "\t") cs_t2) mev_t3
res2 = map (++ "\n") res1
final_result = foldl (++) "" res2

с mev и cs из:

*Main> mev
[[2,-2,-2,-6],[4,2,0,-2],[2,2,4,4],[6,4,2,2],[6,4,2,6]]
*Main> cs
[[0,0,4],[0,1,3],[0,2,2],[1,1,2]]

(эти значения были напечатаны вручную, мне понадобится это для работы с произвольными mev и cs!) У меня изначально есть 2D матрицак которой я применял последовательность операций до тех пор, пока не получил желаемый результат.

Это работает, но теперь я хотел бы заключить всю эту логику в одну функцию (назовем ее matrix_transf).Текущий код привязан к тому, что возвращают matrixExpValues и canonicalSt, и я хотел бы иметь что-то вроде

matrix_transf mev cs = 
    ...all those transformations
    ...until I get to final_result

Любая критика приветствуется (она мне нужна, чтобы я могла ее улучшить!)Я верю, что хорошие программисты на Haskell, вероятно, подойдут к этому совершенно по-другому, и это то, что я хочу знать!

Ответы [ 3 ]

13 голосов
/ 03 декабря 2010
  1. Знай библиотеку. Например, foldl (++) "" x можно заменить на concat, ++ "\t" и т. Д. Можно сделать Data.List.intercalate и т. Д.

  2. Вы можете использовать where и let для определения локальных «переменных».

Предположим, вы хотите преобразовать 2 списка в форму

004:    2    -2   -2   -6
013:    4    2    0    -2
...

тогда я бы написал

import Data.List

matrix_transf mev cs = 
   unlines $ zipWith processEntry mev cs
   where processEntry mev_entry cs_entry = 
            concatMap show cs_entry ++ ":\t" ++ 
            intercalate "\t" (map show mev_entry)
*Main> putStrLn $ matrix_transf [[2,-2,-2,-6],[4,2,0,-2],[2,2,4,4],[6,4,2,2],[6,4,2,6]] [[0,0,4],[0,1,3],[0,2,2],[1,1,2]]
004:    2   -2  -2  -6
013:    4   2   0   -2
022:    2   2   4   4
112:    6   4   2   2

(Обратите внимание, что это отличается от вашей функции, когда конечные вкладки не существуют.)

8 голосов
/ 03 декабря 2010

Сначала я хотел бы сказать, что то, что я собираюсь показать вам, не является оптимальным (например, код KennyTM выглядит намного лучше.) Но я хотел бы показать вам, как будет выглядеть ваш код, если вы измените intXxsToStringXxs до map (map show) и постоянно применять правило:

  • map f (map g xs) ==> map (f.g) xs

при включении определений, когда это возможно. Кроме того, чтобы он выглядел лучше, я применил следующие правила:

  • foldl (++) "" ==> concat
  • concat (map f xs) ==> concatMap f xs
  • concatMap (++ "\n") ==> unlines

После большой переписки вы получите следующее:

cs_t3  = map ((++ ":\t") . concatMap show) cs 
mev_t3 = map (concatMap ((++"\t") . show)) mev 
final_result = unlines (zipWith (++) cs_t3 mev_t3) 

Я знаю, это выглядит не намного лучше, но теперь вам не понадобится много времени, чтобы понять, что вы можете написать matrix_transf следующим образом:

matrix_transf mev cs = unlines (zipWith (++) (starts cs) (endings mev))

starts  = map ((++ ":\t") . (concatMap show)) 
endings = map (concatMap ((++"\t") . show))     

или даже так:

matrix_transf mev cs = unlines . zipWith (++) starts $ endings
    where starts  = map ((++ ":\t") . (concatMap show)) cs 
          endings = map (concatMap ((++"\t") . show)) mev 
0 голосов
/ 13 марта 2013

Забавно, что предыдущие решения по-прежнему обрабатывают вкладку после двоеточия по-разному по сравнению с вкладкой после каждого поля.Когда я выкидываю таблицу, я обычно рассматриваю каждое поле как начинающееся с вкладки, а не заканчивающееся вкладкой.Я также думаю, что версия от @KennyTM более читабельна:

matrix_transf mev cs = 
   unlines $ zipWith processEntry mev cs
   where processEntry mev_entry cs_entry = 
            concatMap show cs_entry ++ ":" ++ 
            concapMap (("\t" ++) . show) mev_entry
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...