Что случилось с этой реализацией quicksort с помощью Arrows?

Хорошо, поэтому я подумал о том, чтобы повеселиться со стрелками. Я попытался напрямую перевести сексурированную операционную систему Haskell на реализацию, в которой вместо этого используются стрелки. Но это работает неправильно.

import Control.Arrow

qs :: Ord a => [a] -> [a]
qs = isEmpty >>> right (head &&& tail 
                        >>> first ((qs.) . filter . (<) 
                                   &&& (\x -> (x:) . qs . filter (>=x)))
                        >>> first (uncurry (&&&)) 
                        >>> uncurry id 
                        >>> uncurry (++)) 
             >>> extract
  where 
    isEmpty [] = Left []
    isEmpty x  = Right x
    extract (Left x)  = x
    extract (Right x) = x

Может ли кто-то выявить проблему?

Ответ 1

Проблема в том, что вы действительно не разделяете tail, два сравнения не дополняют друг друга. Это становится очевидным, когда мы пишем первый как лямбда:

first ( (\x -> qs. . filter (x<))
    &&& (\x -> (x:) . qs . filter (>=x)) )

когда вы хотите, очевидно,

first ( (\x -> qs. . filter (<x))
    &&& (\x -> (x:) . qs . filter (>=x)) )

или

first ( (qs.) . filter . (>)
    &&& (\x -> (x:) . qs . filter (x<=)) )

Кстати, я бы предпочел app более uncurry id.

Ответ 2

Предикат первого фильтра неверен.

(qs.) . filter . (<)

должен быть

(qs.) . filter . (>)