首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有异构递归无穷大且依赖类型参数的类方法

具有异构递归无穷大且依赖类型参数的类方法
EN

Stack Overflow用户
提问于 2014-10-08 08:23:30
回答 1查看 147关注 0票数 3

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

让下一个工作“深度排序”

代码语言:javascript
复制
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 ...

例如

代码语言:javascript
复制
sample :: [Maybe [[Int]]]
sample = [ Just [[5, 3, 7, 1], [6, 0]]
         , Nothing
         , Just [[8, -1], []]
         ]

main = print $ deepSort sample

写入

代码语言:javascript
复制
[Nothing,Just [[],[-1,8]],Just [[0,6],[1,3,5,7]]]

但是现在我想将排序标准参数化,来做一些类似的事情(不工作)

代码语言:javascript
复制
main = print $ deepSortBy sample
                          ( By   (compare `on` someCriteria1)
                          $ By   (compare `on` someCriteria2)
                          $ By   (compare `on` someCriteria3)
                          $ Then (compare `on` someCriteria4)
                          )

我的问题是如何定义“异构递归无限类型”参数(或任何名称)。

我想是的

代码语言:javascript
复制
By (f1 (f2 ... (fN a) ...)
   (By (f2 ... (fN a) ...)
       ...
               Then (fN a)
   )

注意:在deepSort示例中,嵌套容器按照默认的Ord实例进行排序;deepSortBy的含义是为每个嵌套容器提供显式的Ord比较箱函数。因为容器是f1 (f2 (f3 ... (fN a)...),所以可以/应该以By comparer1 (By comparer2 (By ...的形式提供标准。当然,其他方法可能更好。

此外,可能存在一个更好的"Haskell方法“,但我希望(如果可能的话)

  • 我的“按课”方法是否有直接的解决办法?
  • 什么是更好的"Haskell方法“来解决这种问题?
  • 图书馆解决了这个问题?

谢谢!

编辑的

我有一种可能的解决方案(发布作为解决方案,它是工作的!:D )

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-10-08 19:28:08

任何可以是横越的结构都可以排序。Maybe[]都是Traversable。我们可以捕捉到这样的想法:所有的Traversable Functor都可以按照sortBy的定义进行排序。它的工作方式是列出结构中的所有数据,对列表进行排序,然后从左到右遍历结构,用列表中的第一个项替换每个项,并将列表的其余部分带过去。

代码语言:javascript
复制
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中应用一个函数。它只是一个捕捉这种模式的方便函数。

代码语言:javascript
复制
deepSortBy :: Traversable f => (b -> b -> Ordering) -> (a -> b) -> f a -> f b
deepSortBy o f = sortBy o . fmap f

我们可以方便地用deepSortBy对你的样品进行排序。

代码语言:javascript
复制
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被排序到

代码语言:javascript
复制
[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就会把它们放在相反的顺序上。如果期望的结果是

代码语言:javascript
复制
[Nothing,Just [[],[-1,8]],Just [[0,6],[1,3,5,7]]]

我们需要做更多的工作来捕捉内心的比较。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26252289

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档