Последствия фолд против фолд (или фолд)

Я включаю свои представления из моих контроллеров. Я также определяю расположение файлов, чтобы упростить обслуживание.

config.php

define('DIR_BASE',      dirname( dirname( __FILE__ ) ) . '/');
define('DIR_SYSTEM',    DIR_BASE . 'system/');
define('DIR_VIEWS',     DIR_SYSTEM . 'views/');
define('DIR_CTLS',      DIR_SYSTEM . 'ctls/');
define('DIR_MDLS',      DIR_SYSTEM . 'mdls/');
define('VIEW_HEADER',   DIR_VIEWS . 'header.php');
define('VIEW_NAVIGATION',   DIR_VIEWS . 'navigation.php');
define('VIEW_FOOTER',   DIR_VIEWS . 'footer.php');

Теперь у меня есть вся информация, которую мне нужно, просто включив config.php.

controller.php

require( '../config.php' );
include( DIR_MDLS . 'model.php' );

$model = new model();
if ( $model->getStuff() ) {
    $page_to_load = DIR_VIEWS . 'page.php';
}
else {
    $page_to_load = DIR_VIEWS . 'otherpage.php';
}

include( VIEW_HEADER );
include( VIEW_NAVIGATION );
include( DIR_VIEWS . $page_to_load );
include( VIEW_FOOTER );
146
задан MicroVirus 8 March 2016 в 01:48
поделиться

7 ответов

Рекурсия для foldr f x ys, где ys = [y1,y2,...,yk] похож

f y1 (f y2 (... (f yk x) ...))

, тогда как рекурсия для foldl f x ys похожа

f (... (f (f x y1) y2) ...) yk

важное различие здесь, то, что, если результат f x y может быть вычислен с помощью только значение x, то foldr не должен' исследовать весь список. Например

foldr (&&) False (repeat False)

возвраты False, тогда как

foldl (&&) False (repeat False)

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

, С другой стороны, foldl' хвост, рекурсивный и строгий. Если Вы знаете, что необходимо будет пересечь целый список, неважно, что (например, суммируя числа в списке), то foldl' больше пространства - (и вероятно время-) эффективный, чем [1 115].

165
ответ дан Matthias Braun 8 March 2016 в 01:48
поделиться

Причина foldl' предпочтена foldl для 99% всего использования, то, что это может работать в постоянном пространстве за большей частью использования.

Берут функцию sum = foldl['] (+) 0. Когда foldl' используется, сумма сразу вычисляется, таким образом применение sum к бесконечному списку будет просто работать навсегда, и скорее всего в постоянном пространстве (если you’re с помощью вещей как Int с, Double с, Float с. Integer с будет использовать больше, чем постоянное пространство, если число станет больше, чем maxBound :: Int).

С [1 110], преобразователь создается (как рецепт того, как получить ответ, который может быть оценен позже, вместо того, чтобы хранить ответ). Эти преобразователи могут поднять много пространства, и в этом случае, it’s намного лучше для оценки выражения, чем сохранить преобразователя (ведущий к стеку overflow… и продвижение Вас to… о, не берите в голову)

Hope, которая помогает.

18
ответ дан Greg Bacon 8 March 2016 в 01:48
поделиться

Их семантика отличается так, Вы не можете просто чередоваться foldl и foldr. Тот складывает элементы слева, другой справа. Тем путем оператор применяется в различном порядке. Это имеет значение для всех неассоциативных операций, таких как вычитание.

Haskell.org имеет интересное статья о предмете.

33
ответ дан MicroVirus 8 March 2016 в 01:48
поделиться

Вскоре, foldr лучше, когда функция аккумулятора ленива на своем втором аргументе. Считайте больше в Haskell Wiki Переполнение стека (предназначенная игра слов).

23
ответ дан stites 8 March 2016 в 01:48
поделиться

Между прочим, Ruby inject и Clojure reduce составляют foldl (или foldl1 , в зависимости от на какой версии вы используете). Обычно, когда в языке есть только одна форма, это левая складка, включая Python reduce , Perl List :: Util :: reduce , C ++ create ], C # Aggregate , Smalltalk inject: into: , PHP array_reduce , Mathematica Fold и т. Д. Common Lisp's reduce 1145246] по умолчанию используется левое сгибание, но есть возможность правого сгиба.

14
ответ дан 23 November 2019 в 22:25
поделиться

Как указывает Конрад , их семантика различна. У них даже нет одного и того же типа:

ghci> :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
ghci> :t foldl
foldl :: (a -> b -> a) -> a -> [b] -> a
ghci> 

Например, оператор добавления списка (++) может быть реализован с помощью foldr as

(++) = flip (foldr (:))

, а

(++) = flip (foldl (:))

выдаст ошибку типа.

6
ответ дан 23 November 2019 в 22:25
поделиться

Foldr выглядит так:

Right-fold visualization

Foldl выглядит так:

Left-fold visualization

Context: Сгиб на Haskell Wiki

55
ответ дан 23 November 2019 в 22:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: