[Haskell-cafe] Dynamically altering sort order

wren ng thornton wren at freegeek.org
Fri Apr 24 20:29:30 EDT 2009


Denis Bueno wrote:
> Hi all,
> 
> Suppose I have the following interface to a sorting function:
> 
>     sort :: (Ord a) => [a] -> IO [a] -- sort large, on-disk array of records
> 
> but I don't have a sortBy where you can simply pass a compare function.

Why don't you have sortBy?


> Wrapped around this is a command-line program which should allow the
> user to specify different orderings on Records.  For example, if the
> Record has three fields, the user should be able to say "sort only on
> the first two".
> 
> Is there an Ord instance that can be dynamically changed in this way?

The only way to *dynamically* change the Ord instance is to have some 
language of newtypes wrapping records, each with and Ord instance. Then 
to have the user pass in a newtype name on the command line, parse that 
to know which constructor to use, map that constructor over the [a], and 
call sort.

If you had a sortBy function, this could be extended a good deal by 
developing an AST language for expressing sorting functions, and then 
the user could specify the whole AST on the command line, you could 
parse the string into an AST and then have a function to interpret the 
AST as a sorting function which you then pass to sortBy. Actually, this 
sounds like a fun little program to add to the Unix toolbox.



If, however, you wanted to (statically) derive a sortBy function given 
only the sort function, then you only need one Ord instance: namely one 
that packages up a comparison function with the values, as with your 
idea: (but...)

> My first idea is something like this:
> 
>     data CompareRecord = CR{ rCompare :: Record -> Record -> Ordering,
> unCR :: Record }
>     instance Ord CompareRecord where
>         compare (CR cmp x) (CR _ y) = cmp x y
> 
> where the rCompare field would be a function that is based on the
> flags passed to the command-line problem.  But this has an ugly
> asymmetry.

More than just an ugly asymmetry, it's easy to get bugs here because 
there's no assurance that we have the same comparison function packaged 
up on both sides, and so that means 'compare' is no longer commutative. 
If you define sortBy using the Schwartzian transform like Martijn 
suggested, though, then we can show that at least it's right for this 
use case.

-- 
Live well,
~wren


More information about the Haskell-Cafe mailing list