8

レコードのリストがあり、中央値をとって要約したいとしましょう。より具体的には、私が持っているとしましょう

data Location = Location { x :: Double, y :: Double }

測定値のリストがあり、それを median に要約したいLocationので、次のようになります。

Location (median (map x measurements)) (median (map y measurements))

それは問題ありませんが、次のようにさらにネストされたものがある場合はどうなりますか。

data CampusLocation = CampusLocation { firstBuilding :: Location
                                      ,secondBuilding :: Location }

のリストがあり、中央値がすべてのフィールドに再帰的に適用されるCampusLocationsummary が必要です。CampusLocation

Haskellでこれを行う最もクリーンな方法は何ですか? レンズ?ユニプレート?

編集:ボーナス:

要約したいフィールドを含むレコードの代わりに、暗黙のリストがあったとしたら? 例えば:

data ComplexCampus = ComplexCampus { buildings :: [Location] }

それぞれの長さが同じであると仮定して、どのように a[ComplexCampus]を aに要約できますか?ComplexCampusbuildings

4

1 に答える 1

5

summarize :: [ComplexCampus] -> ComplexCampusこれは、レンズとユニプレートを使用して(前述のように)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

ここでバイプレートを使用するのはやり過ぎかもしれませんが、場所のリストでaverageLoc使用してすべてのフィールドとすべてのフィールドを取得します。aを 1 つにまとめたい場合は、すべての値と最上位レベルのすべての値を抽出するために使用できます。biplatexyComplexCampusLocationbiplatexyComplexBuilding

例えば:

campusLocs' ^.. biplate . xすべての x 値とcampusLocs' ^.. biplate . yすべての y 値が得られます

同様に、すべての場所を取得するには、次のようにします。

(campusLocs' ^.. biplate) ::[Location]

または、すべての Double が必要な場合: (campusLocs' ^.. biplate) ::[Double]

于 2014-08-28T06:18:20.700 に答える