具有异构递归无限和依赖类型参数的类方法

时间:2014-10-08 08:23:30

标签: haskell recursion dependent-type

我一直在玩"异构的递归无限类型" (一些更好的标题?)。

让下一个工作" 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)

1 个答案:

答案 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 idlistToMaybe避免了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]]]

我们必须做更多的工作来捕捉内在的比较。