我一直在玩"异构的递归无限类型" (一些更好的标题?)。
让下一个工作" Deep Sort"
class Ord f => DeepSort f where
deepSort :: f -> f
deepSort = id
instance DeepSort Int where
-- and so on ...
instance DeepSort a => DeepSort [a] where
deepSort = sort . map deepSort
instance DeepSort a => DeepSort (Maybe a) where
deepSort = fmap deepSort
-- and so on ...
例如
sample :: [Maybe [[Int]]]
sample = [ Just [[5, 3, 7, 1], [6, 0]]
, Nothing
, Just [[8, -1], []]
]
main = print $ deepSort sample
写入
[Nothing,Just [[],[-1,8]],Just [[0,6],[1,3,5,7]]]
但现在我希望参数化排序标准,做一些像(不工作)
main = print $ deepSortBy sample
( By (compare `on` someCriteria1)
$ By (compare `on` someCriteria2)
$ By (compare `on` someCriteria3)
$ Then (compare `on` someCriteria4)
)
我的问题是如何定义"异构递归无限类型" 参数(或任何名称)。
我认为是
By (f1 (f2 ... (fN a) ...)
(By (f2 ... (fN a) ...)
...
Then (fN a)
)
注意:在deepSort
示例中,嵌套容器按默认Ord
实例升序排序; deepSortBy
的意义是为每个嵌套容器提供明确的Ord
比较函数。由于容器为f1 (f2 (f3 ... (fN a)...)
,因此标准可以/应该以{{1}}的形式提供。但当然可能是更好的其他方法。
此外,可能存在更好的" Haskell方法" 但我希望(如果可能)
通过类" 方法存在一些直接解决方案"
对于这类问题," Haskell方法" 有什么好处?
有些图书馆在解决这个问题吗?
谢谢!!!
EDITED
我有一种可行的解决方案方法(作为解决方案发布,它的工作原理!:D)
答案 0 :(得分:4)
可以对任何可以traversed的结构进行排序。 Maybe
和[]
都是Traversable
。我们可以捕获所有Traversable
Functor
s可以按照sortBy
的以下定义进行排序的想法。它的工作原理是列出结构中的所有数据,对列表进行排序,然后从左到右遍历结构,用列表中的第一项替换每个项目,并将列表的其余部分放在一起。
import qualified Data.List as List
import Data.Foldable
import Data.Traversable
sortBy :: Traversable f => (a -> a -> Ordering) -> f a -> f a
sortBy o f = snd . mapAccumL (\(h:t) _ -> (t, h)) sorted $ f
where
sorted = List.sortBy o . toList $ f
当你deepSortBy
某事时,你只是在排序之前在Traversable
Functor
内部应用一个函数。它只是一种便利功能,可以捕捉到这种模式。
deepSortBy :: Traversable f => (b -> b -> Ordering) -> (a -> b) -> f a -> f b
deepSortBy o f = sortBy o . fmap f
我们可以方便地根据deepSortBy
对您的样本进行排序。
sample :: [Maybe [[Int]]]
sample = [ Just [[5, 3, 7, 1], [6, 0]]
, Nothing
, Just [[8, -1], []]
]
sampleSorter :: [Maybe [[Int]]] -> [Maybe [[Int]]]
sampleSorter =
deepSortBy (compare `on` isJust) $
deepSortBy (compare `on` length) $
deepSortBy (compare `on` listToMaybe) $
sortBy compare
最后一行sortBy compare
相当于deepSortBy compare id
。 listToMaybe
避免了head
会抛出的错误。
请注意,这不会重复使用更深层次的比较来破坏外部比较中的关系。例如,sample
已排序为
[Nothing,Just [[0,6],[1,3,5,7]],Just [[],[-1,8]]]
在Just [[0,6],[1,3,5,7]]
上进行比较时, Just [[],[-1,8]]
和isJust
相互关联,[[0,6],[1,3,5,7]]
与[[],[-1,8]]
和length
进行比较。如果使用内部比较来打破这些联系,listToMaybe
会将这些联系起来。如果所需的结果是
[Nothing,Just [[],[-1,8]],Just [[0,6],[1,3,5,7]]]
我们必须做更多的工作来捕捉内在的比较。