从数据类型

时间:2018-02-23 15:32:35

标签: haskell

我正在尝试在包含许多字段的数据类型中返回具有特定Status的键。我尝试了一些东西,但没有任何东西甚至编译!任何人都有我可以使用的小费吗?

data Configuration v = Configuration {
configurationMap   :: Map.Map v Status,
configurationGraph :: Graph v
}

verticesByStatus :: Ord v => Status -> Configuration v -> [v]
verticesByStatus  ???

3 个答案:

答案 0 :(得分:1)

可能有一种更优雅的方式来表达这一点,但这是一个解决方案:

  verticesByStatus status (Configuration map graph) = fst <$> (filter ((== status) . snd) $ M.assocs map)

那么这里发生了什么?首先,我们对配置参数进行模式匹配,以提取它的两个组件,并将它们分配给变量mapgraph。现在让我们打破右手边:

  fst <$> (filter ((== status) . snd) $ Map.assocs map)
                                            ^-- This comes from the Data.Map package and splits a map into a list of tuples of key/value pairs. 
                            ^-- Here, we filter our new list of key/values based on the values, and find only those that match the input status 
  ^-- Last, we fmap the function fst over the whole list to extract only the keys that match your given status

表达此功能的另一种方法是通过eta-reduction来简化它。一种方法是使用configurationMap函数来提取配置的那部分而不是模式匹配:

  verticesByStatus status = fmap fst . filter ((== status) . snd) . Map.assocs . configurationMap

答案 1 :(得分:0)

Data.Map中的地图有filter,可以直接用于配置地图:

verticesByStatus :: Ord v => Status -> Configuration v -> [v]
verticesByStatus status = Map.keys . Map.filter (== status) . configurationMap

Map.keys生成地图中的键列表。 (如果您想要一个值列表,可以使用Map.elems或等同于toList中的Data.Foldable。请注意,有些令人困惑的是,后者与... {0}相同Map.toList,它会生成一个键值对列表,就像jkeuhlen的答案中的Map.assocs一样。)

答案 2 :(得分:0)

verticesByStatus :: Ord v => Status -> Configuration v -> [v]
verticesByStatus status (Configuration cMap cGraph) =
    [ v
    | v <- vertices cGraph,
      Just(status) == (Map.lookup v cMap)]

一些注意事项:

  • 我会选择避免Map.assocs,因为它需要花费额外的O(n)才能运行,您可以获得配置图中的值,而无需先将其转换为元组列表(请参阅Map docs)。

  • 我选择了列表理解,而不是将mapfilter组合在一起,因为我发现它更容易阅读(我在阅读this article后选择的内容)

  • 我们可以检查查找是否返回JustNothing,然后使用JustfromJust的情况下提取值但是这将是更多的代码,可能更难阅读。它看起来像是:

    verticesByStatus :: Ord v => Status -> Configuration v -> [v]
    verticesByStatus status (Configuration cMap cGraph) =
        [ v
        | v <- vertices cGraph,
          let vStatus = Map.lookup v cMap,
          if (isJust vStatus) then (status == (fromJust vStatus)) else False]
    
相关问题