在Haskell中表达长合成链
(不重要的背景信息/动机) 我当时正在实现一个不同版本的在Haskell中表达长合成链,haskell,coding-style,function-composition,Haskell,Coding Style,Function Composition,(不重要的背景信息/动机) 我当时正在实现一个不同版本的nub,灵感来自于它的使用方法 地图头。小组。sort比调用nub更有效。然而,在我们的情况下,秩序是重要的 所以我开始写一个“更好”的要点,类似于订单不重要的版本。我最终得到了这样的结果: mynub = unsort . map head . groupBy (\x y -> fst x == fst y) . sortBy (comparing fst) . rememberPosition rememberPosition
nub
,灵感来自于它的使用方法
地图头。小组。sort
比调用nub
更有效。然而,在我们的情况下,秩序是重要的
所以我开始写一个“更好”的要点,类似于订单不重要的版本。我最终得到了这样的结果:
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(nlogn),而不是原始的nub的O(n2)。但这不是重点。问题是,太长了!它其实并没有那么复杂,但很长(我是那些讨厌超过80列或StackOverflow代码块上的水平滚动条的人之一)
(问题)
在Haskell中,有什么更好的方法可以表达这样的长函数组合链?线宽很容易解决:) 但我几乎不习惯从右到左阅读作文。自上而下有点过分。 Arrow或(>>>)=flip(.)在我看来更好看,但我不知道它是否是惯用的
> mynub = { rememberPosition
> >>> sortBy (comparing fst)
> >>> groupBy (\x y -> fst x == fst y)
> >>> map head
> >>> unsort
> }
拆分该行,并使用布局:
mynub = unsort
. map head
. groupBy ((==) `on` fst)
. sortBy (comparing fst)
. rememberPosition
(>>>)
有点单一,但定义在库中:需要注意的三个重要事项nub
只是有一个Eq a
约束,而您的版本有一个Ord a
约束nub
适用于无限列表,而您的版本不适用。另外,nub
的最坏情况可能比您的代码更糟,但它的最佳情况比您的代码更好。最显著的差异是Ord a
约束。如果你允许,你可以写一些更复杂的东西,在最坏的情况下是O(n logn),在最好的情况下几乎和nub
一样好,并且可以在无限列表上工作。但它涉及非列表数据结构。
mynub = unsort
. map head
. groupBy ((==) `on` fst)
. sortBy (comparing fst)
. rememberPosition