【问题标题】:Pattern matching over Data.MapData.Map 上的模式匹配
【发布时间】:2014-07-13 10:29:44
【问题描述】:

我进行了搜索,但令人惊讶的是,没有找到任何可以帮助我对其执行模式匹配的东西。我需要确保在我的地图“变量”中恰好有 3 个键。就是这样。而不是“如果...然后...其他”,我想使用模式匹配,因为它更容易阅读并且似乎更哈斯克尔方式。所以:

myFunction :: Map String String
--.......................

main = do
  let var1 = myFunction
  -- how do I ensure it has exactly 3 keys in it and if not raise an error?  

【问题讨论】:

  • 如果有任何非 Haskell-wayish 的东西,那么可能你有一个仅适用于特定大小的地图的功能。您的类型可能与您需要的不匹配。

标签: haskell


【解决方案1】:

您无法对抽象数据类型进行模式匹配,因为您无权访问它们的构造函数¹,因此您必须使用“Data.Map”模块提供的函数。

但请注意,您可以使用 size :: Map k a -> Int 函数。如果你不喜欢if .. then .. else ..(这绝不是错误或不成熟的),你可以使用模式守卫:

foo m | size m == 3 = ...
      | otherwise = error "Not three element"

¹ 在此忽略视图模式和模式同义词,但这些只是句法上的补充。

【讨论】:

  • 通常我会说sizelength un-Haskellish,但在这里可以说是正确的做法。
  • 为什么是抽象数据类型?
  • 导出类型的模块不会同时导出其构造函数。如果可以,您可能会构建无效的搜索树,然后Map 函数会突然给出错误的结果。
  • 好的。有没有办法一次获得这 3 个值?
【解决方案2】:

你可以在M.toList上进行模式匹配:

import qualified Data.Map as M
-- ...
main = do
  case (M.toList myFunction) of
    [a,b,c] -> ... -- exactly 3 arguments
    _       -> ... -- more or less than 3 arguments

【讨论】:

  • 我怎么知道哪个值对应哪个键?
  • a, b 和 c 是一个元组(key, value)
  • @AlexanderSupertramp 你不会,Maps 不会保留顺序,因为它们使用比 [(key, value)] 类型更有效的实现,IIRC 它是一个二叉搜索树,但是你会有查看toList 的来源以找出返回的顺序。简而言之,没有一个好方法可以确定哪个是哪个。如果您需要该功能,我建议您只需(查找您需要的每个元素](gist.github.com/bheklilr/04a56336e5917d3ec5b1)。如果在该Map 中找不到这三个键,则此示例将保留顺序并返回Nothing。跨度>
猜你喜欢
  • 1970-01-01
  • 2015-09-30
  • 1970-01-01
  • 1970-01-01
  • 2019-03-19
  • 2016-11-27
  • 2018-11-09
  • 2023-03-05
  • 1970-01-01
相关资源
最近更新 更多