在一元上下文中使用 Data.Map

发布于 2024-12-22 14:12:46 字数 261 浏览 2 评论 0原文

我正在操作的地图具有单键(IO Double 类型)。我需要在这张地图上使用 findMax 。我可以使用 liftM 来实现此目的吗?

Map.findMax $ Map.fromList [(f x, "X"), (f y, "Y"), (f z, "Z")]

这里 f x 的类型为 IO Double

A map that I am operating on has monadic keys (of type IO Double). I need to use findMax on this map. Can I use liftM for this?

Map.findMax $ Map.fromList [(f x, "X"), (f y, "Y"), (f z, "Z")]

Here f x has type IO Double.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

盗心人 2024-12-29 14:12:46

将 IO 类型的值作为映射中的键实际上没有意义。对于某些 t 类型,IO t 类型的值可以被视为一个“程序”,每次生成一个 t 类型的值运行:您可以运行它多次,每次都可能产生不同的值。

所以,你可能想要的是首先运行“程序”以获得一些结果;这些结果可以成为你的地图的关键。

例如,如果您有一个

f :: Int -> IO Int

接受整数并可能有效地计算整数的“程序”,并且您需要运行 [1 .. 10] 的输入来获取映射的键,您可以按如下方式继续:

createMap :: IO (Map Int Int)
createMap = do
  keys <- mapM f [1 .. 10]
  return $ foldr (\k -> Map.insert k (g k)) Map.empty keys

这假设通过函数 createMap 从键计算值,

g :: Int -> Int

生成从整数到整数的映射;它在 IO-monad 中返回它,因为用于填充映射的键可能受“程序”f 运行的环境的影响。

您的问题

在您的情况下,这意味着您想要计算的最大值也必须在 IO-monad 中生成:

getMax :: Int -> Int -> Int -> IO (Double, String)
getMax x y z = do
  keys <- mapM f [x, y, z]
  let entries = zip keys ["X", "Y", "Z"]
  return (Map.findMax (Map.fromList entries))

增量构建映射

当然不需要创建映射一次性构建,但也可以增量构建:

f :: Int -> IO Int
f = ...

g :: Int -> Int
g = ...

createMap :: IO (Map Int Int)
createMap = do
  -- create the empty map
  let m0 = Map.empty

  -- insert an entry into the map
  k1 <- f 1
  let m1 = Map.insert k1 (g k1) m0

  -- extend the map with another entry
  k2 <- f 2
  let m2 = Map.insert k2 (g k2) m1

  -- return the map
  return m2

It doesn't really make sense to have IO-typed values as keys in a map. A value of type IO t for some type t can be thought of as a "program" that produces a value of type t each time it is run: you can run it multiple times and every time it may produce a different value.

So, want you probably want is to first run the "program" to obtain some results; these results then can be the keys of your map.

For example, if you have a "program"

f :: Int -> IO Int

that takes integers and computes, potentially effectfully, integers, and you need to run in on inputs from [1 .. 10] to obtain the keys of your map, you could proceed as follows:

createMap :: IO (Map Int Int)
createMap = do
  keys <- mapM f [1 .. 10]
  return $ foldr (\k -> Map.insert k (g k)) Map.empty keys

This assumes that the values are computed from the keys by a function

g :: Int -> Int

createMap produces a map from integers to integers; it returns it in the IO-monad, because which keys are used to populate the map is possibly subject to the environment in which the "program" f was run.

Your Problem

In your situation, this means that the maximal value you want to compute, has to be produced in the IO-monad as well:

getMax :: Int -> Int -> Int -> IO (Double, String)
getMax x y z = do
  keys <- mapM f [x, y, z]
  let entries = zip keys ["X", "Y", "Z"]
  return (Map.findMax (Map.fromList entries))

Constructing the map incrementally

The map of course does not need to be created in one go, but can also be constructed incrementally:

f :: Int -> IO Int
f = ...

g :: Int -> Int
g = ...

createMap :: IO (Map Int Int)
createMap = do
  -- create the empty map
  let m0 = Map.empty

  -- insert an entry into the map
  k1 <- f 1
  let m1 = Map.insert k1 (g k1) m0

  -- extend the map with another entry
  k2 <- f 2
  let m2 = Map.insert k2 (g k2) m1

  -- return the map
  return m2
划一舟意中人 2024-12-29 14:12:46

您应该在插入地图之前执行单子操作,如下所示

insertValue :: Value -> Map Key Value -> IO (Map Key Value)
insertValue value m = do
  key <- calculateKey value
  return $ Map.insert key value m

calculateKey :: Value -> IO Key

You should execute the monadic action before inserting into the map, like this:

insertValue :: Value -> Map Key Value -> IO (Map Key Value)
insertValue value m = do
  key <- calculateKey value
  return $ Map.insert key value m

where

calculateKey :: Value -> IO Key
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文