Ответ 1
Только один раз:
Эффективность: когда одна и та же функция просмотра применяется в множественные ветки определения функции или выражение case (например, в
size
выше), GHC пытается собрать эти приложений в одно вложенное выражение case, так что представление функция применяется только один раз. Сбор образцов в GHC следует матричный алгоритм, описанный в главе 4 Реализация языков функционального программирования. Когда верхние строки первого столбца матрицы - все шаблоны представлений с "то же" выражение, эти шаблоны преобразуются в один вложенный дело. Это включает в себя, например, смежные шаблоны просмотра, которые выстраиваются в линию в кортеже, как вf ((view -> A, p1), p2) = e1 f ((view -> B, p3), p4) = e2Текущее понятие, когда два выражения шаблона представления являются "то же самое" очень ограничено: это даже не полное синтаксическое равенство. Однако он включает переменные, литералы, приложения и кортежи; например, два экземпляра
view ("hi", "there")
будут собраны. Однако текущая реализация не сравнивается с альфа-эквивалентность, поэтому два экземпляра(x, view x -> y)
не будут объединены.
Что касается вашего фрагмента, проблема в том, что вы не компилируете с оптимизацией; с ghc -O
и ghc -O2
, строка печатается только один раз. Это всегда первое, что нужно проверить, когда у вас есть проблемы с производительностью при использовании GHC:)
(Кстати, Debug.Trace позволяет вам проверять эти вещи без необходимости писать ручные unsafePerformIO
хаки.)