Haskell List Monad - 按参数推广

时间:2017-08-23 02:38:41

标签: haskell list-comprehension monads

让我们想象一下人口(人类)。每个人都有东西,有长度(左臂,右臂,左腿,右腿)。每个人都有东西,可能有宽度(胸部,腰部)。人类可能拥有更多参数。

所有测量类型都是

allMeasurementTypes = [Width, Length, Diameter, Weight] -- and similar things.

对于统计数据,我希望为所有人群提供所有可能的测量对。

类似的东西:

Pair1_LeftLeg Pair1_Waist Pair2_LeftLeg Pair2_Chest Pair3_RightLeg Pair3_Waist...
102           70          102           90          101            70         ...
115           60          115           85          116            60         ...
...           ...         ...           ...         ...            ...        ...

不要告诉我,这里有重复。我知道。但是我更容易让它在统计应用程序中进一步处理。

所以我按照以下方式构建它

allMeasurements :: [Human] -> Seq (Int, [(String, [Double])])
allMeasurements population = mapWithIndex (,) measures
  where
    measures = do
      mTypes <- fromList $ choose allMeasurementTypes 2
      rec1 <- recordsForPeople population $ head mTypes
      rec2 <- recordsForPeople population $ mTypes !! 1
      return [rec1, rec2]

现在我逐行解释。

allMeasurements :: [Human] -> Seq (Int, [(String, [Double])])

此处Int是该对的编号。如果是Pair1,那么String将是"LeftLeg",然后是"Waist"[Double]所有人口中每个度量值的数组。

allMeasurements population = mapWithIndex (,) measures
  where
    measures = do
      mTypes <- fromList $ choose allMeasurementTypes 2

这会迭代所有可能的测量类型对。 choose获取所有可能的对,例如[Width, Length][Width, Diameter] ...

      rec1 <- recordsForPeople population $ head mTypes

假设第一个mType是Lengthrec1遍历所有可能的长度。 rec1遍历("LeftLeg", [102, 115, ...])("RightLeg", [101, 116, ...]) ...

      rec2 <- recordsForPeople population $ mTypes !! 1

假设第二个mType是Widthrec2遍历所有可能的宽度。 rec2遍历("Waist", [70, 60, ...])("Chest", [90, 85, ...]) ...

      return [rec1, rec2]

最后我收集了所有的东西。它为所有人群提供了所有可能的单独测量对的Seq。上面的mapWithIndex只是遍历此完整列表,并在内部注入实际Int个数量的对。我之所以选择Seq只是因为它有mapWithIndex。然后全部用于渲染csvjson

也许我可以做得更好更聪明。 UFF。

这是真正的问题。

除了对表之外,我还想生成三位一体的表。

allTriMeasurements :: [Human] -> Seq (Int, [(String, [Double])])
allTriMeasurements population = mapWithIndex (,) measures
  where
    measures = do
      mTypes <- fromList $ choose allMeasurementTypes 3
      rec1 <- recordsForPeople population $ head mTypes
      rec2 <- recordsForPeople population $ mTypes !! 1
      rec3 <- recordsForPeople population $ mTypes !! 2
      return [rec1, rec2, rec3]

无论如何可以通过参数allMeasurements概括这两个函数allTriMeasurementsn,定义对于2对是2还是3对于三位。

我已经放弃了关于fmap和类似的想法,因为这里(monadic)列表理解所有rec_i <- ...应该一个接一个地去。任何类型的doSomething <$> [0 .. (n-1)]都会破坏结构。

很可能,我做错了。如果除了我之外的任何人都能够理解,这里发生了什么,我将非常感谢任何想法。在我看来,我的代码中最丑陋的地方。

1 个答案:

答案 0 :(得分:1)

if (this.state.islogged) {
    return <Tabs />;
} else {
    return <StackRegistro />;
}

太容易了。我只是忽略了allMeasurements :: Int -> [Human] -> Seq (Int, [(String, [Double])]) allMeasurements k population = mapWithIndex (,) measures where measures = mapM (recordsForPeople population) =<< fromList (choose allMeasurementTypes k) 超级大国。