Подтвердить что ты не робот

Более эффективный код точки или просто терпение?

Я написал следующий код, который берет кучу точек и рисует их на экране с помощью библиотеки глянца.

let s = blocks pes
    pts = map (map mkPt) s  {- stitches to points-}
    lines = map Line pts    {-points to lines -}
    pict = Pictures lines   {- lines to a picture -}
  in do  displayInWindow "My Window" (200, 200) (10, 10) white pict

Он отлично работает, но мне приходит в голову, что существует повторяющийся шаблон: цепочка вызовов функций, результат каждого из которых подается в последний аргумент следующего. Поэтому я реорганизую, удаляя промежуточные переменные, меняя порядок и цепляя функции с композицией функции ( "." ) Следующим образом:

let pict = Pictures . (map Line) . (map $ map $ mkPt) . blocks $ pes
                in do  displayInWindow "My Window" (200, 200) (10, 10) white pict

К счастью, это тоже отлично. Но мне интересно, не напрягаю ли удобочитаемость, или если я просто не привык к чтению и написанию кода стиля без кода. Кроме того, как мне объяснить этот код? Является ли вторая версия более эффективной или просто сложной? Есть ли что-нибудь, что я могу сделать стилистически, чтобы сделать его более ясным?

4b9b3361

Ответ 1

Несколько быстрых предложений:

let pict = Pictures . (map Line) . (map $ map $ mkPt) . blocks $ pes
in do displayInWindow "My Window" (200, 200) (10, 10) white pict

У вас есть лишние вещи, которые можно удалить прямо:

let pict = Pictures . map Line . (map $ map mkPt) . blocks $ pes
in do displayInWindow "My Window" (200, 200) (10, 10) white pict

В любом случае вы не избегаете круглых скобок с термином map (map mkPt), поэтому избавляйтесь от $:

let pict = Pictures . map Line . map (map mkPt) . blocks $ pes
in do displayInWindow "My Window" (200, 200) (10, 10) white pict

Для ясности можно написать цепочку композиций на нескольких строках:

let pict = Pictures 
         . map Line 
         . map (map mkPt) 
         . blocks $ pes
in do displayInWindow "My Window" (200, 200) (10, 10) white pict

Блок do лишний, поскольку он имеет только один оператор, и вы можете перенести окончательное приложение за пределы определения:

let displayPict = displayInWindow "My Window" (200, 200) (10, 10) white
                . Pictures 
                . map Line 
                . map (map mkPt) 
                . blocks
in displayPict pes

Вы можете объединить два map s:

let displayPict = displayInWindow "My Window" (200, 200) (10, 10) white
                . Pictures 
                . map (Line . map mkPt) 
                . blocks
in displayPict pes

Иногда это также более читаемо для длинных цепей, чтобы использовать оператор обратной композиции из Control.Arrow:

let displayPict = blocks
                  >>> map (Line . map mkPt) 
                  >>> Pictures
                  >>> displayInWindow "My Window" (200, 200) (10, 10) white
in displayPict pes

Но все это необязательно; введите свой код по вкусу.

Что касается эффективности, я не вижу причин думать, что они будут разными, как только GHC-оптимизатор будет работать с кодом.

Ответ 2

Точечный стиль может быть хорошим, чтобы очень четко показать, что функция представляет собой просто последовательность преобразований на входе. Очень легко читать что-то вроде:

foo = map show . doThis . doThat . etc

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

foo x = d
    where
        a = etc x
        c = doThis b
        b = doThat a
        d = map show c

Очевидно, что это немного надуманно, но идея состоит в том, что дополнительные определения нужно читать и внимательно следить за тем, чтобы понять, что действительно делает foo. Используется ли a в качестве аргумента для более чем одной вспомогательной функции? Что насчет b? Произошли ли данные через эти вспомогательные функции таким образом, что это было неожиданным? Точный свободный стиль в этом случае говорит: "Вещи просто трансформируются в конвейер, нет никаких странностей, о которых вам нужно подумать"

В других случаях стиль без точек может действительно запутывать вещи. Вообще-то, когда вы выходите из дам и wheres. Таким образом, терпение - не единственная цель, важно также уменьшить умственную нагрузку. (Как прокомментировали другие, точечный стиль не должен иметь разницу в производительности в оптимизированном коде).