паттерны для «симметричных» функций

Попробовать эту новую штуку с stackoverflow, как было предложено :) На самом деле это не относится к haskell, но лучше всего в haskell.

Вот шаблон, который возникает время от времени: функция принимает два аргумента, которые обрабатываются симметрично. mappends часто имеют это свойство. Пример:

-- | Merge sorted lists of ranges.
merge :: (Ord n) => [(n, n)] -> [(n, n)] -> [(n, n)]
merge [] r2 = r2
merge r1 [] = r1
merge r1@((s1, e1) : rest1) r2@((s2, e2) : rest2)
    | e1 < s2 = (s1, e1) : merge rest1 r2
    | e2 < s1 = (s2, e2) : merge r1 rest2
    | s1 >= s2 && e1 <= e2 = merge rest1 r2 -- 1 within 2
    | s2 >= s1 && e2 <= e1 = merge r1 rest2 -- 2 within 1
    | e1 > e2 = merge (merged : rest1) rest2
    | otherwise = merge rest1 (merged : rest2)
    where merged = (min s1 s2, max e1 e2)

Обратите внимание, что обработка 'r1' и «r2» симметрично. На самом деле существует только 4 случая: слияние с нулевым значением дает ненулевой, отсутствие перекрытия дает неизменный диапазон, один, содержащийся в другом, отбрасывает подчиненный диапазон, а перекрытие создает объединенный диапазон и пытается объединить его с остальными.

Тем не менее, каждый случай имеет зеркальный вариант, поэтому получается 8, хотя зеркало 4 можно получить механически. Мало того, что здесь вдвое больше места для ошибок, из-за симметрии ошибки не будут обнаружены проверкой типов. Есть ли название у этого паттерна? Способ исключить повторение? Полагаю, я могу попытаться определить его для списка, а затем написать «mappend ab = mconcat [a, b]», но мне труднее представить себе проблему в общем виде (например, у меня болит голова при мысли о том, в какой список снова включить объединенный интервал). Намного проще определить mappend, а затем извлечь из этого mconcat. Может быть, есть лучший способ придумать вариант списка, чтобы не повредить голову?

Я думаю, что хочу «сосредоточиться» на одном случае, чтобы я мог писать в терминах «то» и «то». Об этом не только легче думать, чем о двух равноправных «r1» и «r2», то и тот-> этот случай должен подразумеваться из этого-> того.

7
задан Don Stewart 6 May 2011 в 18:03
поделиться