[英]Summarize a list of Haskell records
Let's say I have a list of records, and I want to summarize it by taking the median. 假设我有一个记录列表,我想通过取中位数来对其进行总结。 More concretely, say I have
更具体地说,说我有
data Location = Location { x :: Double, y :: Double }
I have a list of measurements, and I want to summarize it into a median Location
, so something like: 我有一个测量值列表,我想将其汇总为一个中值
Location
,如下所示:
Location (median (map x measurements)) (median (map y measurements))
That is fine, but what if I have something more nested, such as: 很好,但是如果我有更多嵌套的东西,例如:
data CampusLocation = CampusLocation { firstBuilding :: Location
,secondBuilding :: Location }
I have a list of CampusLocation
s and I want a summary CampusLocation
, where the median is applied recursively to all fields. 我有一个
CampusLocation
的列表,我想要一个Summary CampusLocation
,其中中值递归地应用于所有字段。
What is the cleanest way to do this in Haskell? 在Haskell中最干净的方法是什么? Lenses?
镜片? Uniplate?
Uniplate?
Edit: Bonus: 编辑:奖金:
What if instead of a record containing fields we want to summarize, we had an implicit list instead? 如果我们没有包含要汇总的字段的记录,而是有一个隐式列表怎么办? For example:
例如:
data ComplexCampus = ComplexCampus { buildings :: [Location] }
How can we summarize a [ComplexCampus]
into a ComplexCampus
, assuming that each of the buildings
is the same length? 我们怎样才能总结出
[ComplexCampus]
成ComplexCampus
,假设每个的buildings
是一样的长度?
Here is an implementation of summarize :: [ComplexCampus] -> ComplexCampus
that uses Lenses w/ Uniplate (as you mentioned) to summarize a list of ComplexCampus a single ComplexCampus. 这是
summarize :: [ComplexCampus] -> ComplexCampus
,它使用带有Uniplate的镜头(如您所述)来汇总单个ComplexCampus的ComplexCampus列表。
{-# Language TemplateHaskell,DeriveDataTypeable #-}
import Control.Lens
import Data.Data.Lens
import Data.Typeable
import Data.Data
import Data.List(transpose,genericLength)
data Location = Location { _x :: Double, _y :: Double } deriving(Show,Typeable,Data)
data CampusLocation = CampusLocation { _firstBuilding :: Location, _firsecondBuilding :: Location }deriving(Show,Typeable,Data)
data ComplexCampus = ComplexCampus { _buildings :: [Location] } deriving(Show,Typeable,Data)
makeLenses ''Location
makeLenses ''CampusLocation
makeLenses ''ComplexCampus
l1 = Location 1 10
l2 = Location 2 20
l3 = Location 3 30
c1 = CampusLocation l1 l2
c2 = CampusLocation l2 l3
c3 = CampusLocation l1 l3
campusLocs = [c1,c2,c3]
c1' = ComplexCampus [l1, l2]
c2' = ComplexCampus [l2, l3]
c3' = ComplexCampus [l1, l3]
campusLocs' = [c1',c2',c3']
average l = (sum l) / (genericLength l)
-- returns average location for a list of locations
averageLoc locs = Location {
_x = average $ locs ^.. biplate . x,
_y = average $ locs ^.. biplate . y
}
summarize :: [ComplexCampus] -> ComplexCampus
summarize ccs = ComplexCampus $ ccs ^.. biplate . buildings ^.. folding transpose . to averageLoc
Using biplate here is likely overkill, but regardless in averageLoc
we use biplate
on the list of locations to get all x
fields and all y
fields. 这里使用双片很可能矫枉过正,但无论在
averageLoc
我们使用biplate
地区的清单上获得所有x
领域和所有y
领域。 If you wanted to summarize a ComplexCampus
into a single Location
we could use biplate
to extract all x
values and all y
values from the top level ComplexBuilding
. 如果你想总结出
ComplexCampus
到一个单一的Location
,我们可以使用biplate
提取所有x
值和所有y
从顶层值ComplexBuilding
。
For example: 例如:
campusLocs' ^.. biplate . x
campusLocs' ^.. biplate . x
gives us all x values and campusLocs' ^.. biplate . y
campusLocs' ^.. biplate . x
给我们所有的x值和campusLocs' ^.. biplate . y
campusLocs' ^.. biplate . y
gives us all y values campusLocs' ^.. biplate . y
给我们所有y值
Likewise, to get all locations, we could just do: 同样,要获取所有位置,我们可以这样做:
(campusLocs' ^.. biplate) ::[Location]
Or, if we wanted every Double: (campusLocs' ^.. biplate) ::[Double]
或者,如果我们希望每个Double:
(campusLocs' ^.. biplate) ::[Double]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.