Выражая длинную цепочку композиций в Haskell

(несущественная фоновая информация/мотивация)

Я использовал другую версию nub, вдохновленную разочарованием в книге Yesod, используя ее.

map head . group . sort более эффективен, чем вызов nub. Однако в нашем случае порядок важен...

Итак, я написал "лучший" нуб, похожий на неважную версию. И я закончил с этим:

mynub = unsort . map head . groupBy (\x y -> fst x == fst y) . sortBy (comparing fst) . rememberPosition

rememberPosition = flip zip [0..]
unsort = map fst . sortBy (comparing snd)

Это, безусловно, делает много дополнительной работы, но это должно быть O (n log n) вместо исходного nub O (n 2). Но это не имеет значения. Проблема в том, что так долго! Это действительно не так сложно, но долго (и я один из тех людей, которые ненавидят более 80 столбцов или горизонтальных полос прокрутки на блоках кода StackOverflow).

(вопрос)

Каковы лучшие способы в Haskell для выражения длинных цепей функционального состава, таких как это?

Ответ 1

Разбейте строку и используйте макет:

mynub = unsort 
      . map head 
      . groupBy ((==) `on` fst)
      . sortBy (comparing fst) 
      . rememberPosition

Ответ 2

ширина строки легко решается:)

> mynub = { unsort 
>         . map head 
>         . groupBy (\x y -> fst x == fst y) 
>         . sortBy (comparing fst) 
>         . rememberPosition
>         }

но я едва привык читать композицию справа налево. Сверху вниз немного. Стрелка или ( → > ) = flip (.) Выглядит приятнее для меня, но я понятия не имею, будет ли это идиоматично

> mynub = { rememberPosition
>       >>> sortBy (comparing fst) 
>       >>> groupBy (\x y -> fst x == fst y) 
>       >>> map head 
>       >>> unsort 
>         }