Expressing long chain of compositions in Haskell
(不重要的背景信息/动机)
我当时正在实施一个不同版本的nub,这是受Yesod图书不鼓励使用它的启发。
map head . group . sort is more efficient than a call to nub. However, in our case, order is important...
号
所以我开始写一个"更好"的nub,类似于订单不重要的版本。最后我得到了:
1 2 3 4
| mynub = unsort . map head . groupBy (\x y -> fst x == fst y ) . sortBy (comparing fst) . rememberPosition
rememberPosition = flip zip [0.. ]
unsort = map fst . sortBy (comparing snd) |
这当然会做很多额外的工作,但是应该是O(n log n)而不是原始的nub的O(n2)。但这不是重点。问题是,时间太长了!它并没有那么复杂,但很长(我是那种不喜欢扩展到80列或StackOverflow代码块上的水平滚动条的人之一)。
(问题)
在haskell中,有什么更好的方法可以表达这样长的功能组成链?
- 需要注意的三个重要事项。nub只是有一个Eq a约束,而您的版本有一个Ord a约束。nub在无限列表中工作,而您的版本不工作。另外,nub的最坏情况可能比您的代码更糟,但最好的情况比您的代码更好。最显著的差异是Ord a约束。如果你允许的话,你可以写一些更复杂的东西,那就是O(n log n)最坏的情况,在最好的情况下几乎和nub一样好,并且可以在无限的列表上工作。但它涉及非列表数据结构。
分解行,并使用布局:
1 2 3 4 5
| mynub = unsort
. map head
. groupBy ((==) `on` fst)
. sortBy (comparing fst)
. rememberPosition |
线条宽度很容易解决:)
1 2 3 4 5 6
| > mynub = { unsort
> . map head
> . groupBy (\x y -> fst x == fst y )
> . sortBy (comparing fst)
> . rememberPosition
> } |
但我几乎不习惯从右向左看作文。从上到下是有点多。arrow或(>>>)=flip(.)对我来说更合适,但我不知道它是否是惯用的
1 2 3 4 5 6
| > mynub = { rememberPosition
> >>> sortBy (comparing fst)
> >>> groupBy (\x y -> fst x == fst y )
> >>> map head
> >>> unsort
> } |
号
- (>>>)是有点不地道,但在base定义:hackage.haskell.org /图书馆/档案/底/最新的包/ DOC / HTML / & hellip;
- 为什么《牙套吗?