servant-util-0.1.0: src/Servant/Util/Dummy/Sorting.hs
{- | Implements plain lexicographical sorting.
Example:
@
sortingSpecApp
:: MyObject
-> SortingSpecApp
DummySortingBackend
[ "id" ?: Int
, "desc" ?: Text
]
sortingSpecApp obj =
fieldSort @"id" (id obj) .*.
fieldSort @"desc" (desc obj) .*.
HNil
@
Next, you use `sortBySpec` to apply sorting.
@
sortObjects sorting = filter (sortBySpec sorting . sortingSpecApp) allObjects
@
-}
module Servant.Util.Dummy.Sorting
( SortingSpecApp
, fieldSort
, sortBySpec
) where
import Universum
import Data.Typeable (cast)
import Servant.Util.Combinators.Sorting.Backend
import Servant.Util.Combinators.Sorting.Base
-- | Implements sorting for beam-postgres package.
data DummySortingBackend
data SomeOrd = forall a. (Typeable a, Ord a) => SomeOrd a
-- | Unsafe instance which assumes that 'SomeOrd' contains the same items inside.
instance Eq SomeOrd where
(==) = (== EQ) ... compare
-- | Unsafe instance which assumes that 'SomeOrd' contains the same items inside.
instance Ord SomeOrd where
SomeOrd a `compare` SomeOrd b =
let b' = cast b ?: error "Compared `SomeOrd`s are different inside"
in a `compare` b'
instance SortingBackend DummySortingBackend where
type SortedValue DummySortingBackend a = a
type BackendOrdering DummySortingBackend = SomeOrd
type SortedValueConstraint DummySortingBackend a = (Typeable a, Ord a)
backendFieldSort field = SortingApp $ \(SortingItemTagged (SortingItem _name order)) ->
case order of
Ascendant -> SomeOrd field
Descendant -> SomeOrd (Down field)
-- | Applies a whole filtering specification to a set of response fields.
-- Resulting value can be put to 'filter' function.
sortBySpec
:: ( backend ~ DummySortingBackend
, allParams ~ AllSortingParams provided base
, ApplyToSortItem backend allParams
)
=> SortingSpec provided base
-> (a -> SortingSpecApp backend allParams)
-> [a] -> [a]
sortBySpec spec mkApp values =
map fst . sortOn snd $
map (id &&& backendApplySorting spec . mkApp) values