在单子上下文中使用Data.Map [英] Using Data.Map in monadic context

查看:55
本文介绍了在单子上下文中使用Data.Map的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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")]

此处f x的类型为IO Double.

推荐答案

在地图中使用IO类型的值作为键实际上没有任何意义.某些类型t的类型IO t的值可以被认为是一个程序",它每次运行时都会产生类型t的值:您可以多次运行它,并且每次可能会产生一个t类型值.不同的值.

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

需要整数并计算(可能有效地是整数),并且您需要在[1 .. 10]的输入上运行才能获取地图的键,您可以按以下步骤进行操作:

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产生从整数到整数的映射;它会在IO -monad中返回它,因为使用哪个键填充地图可能受运行程序" f的环境的影响.

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.

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

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

这篇关于在单子上下文中使用Data.Map的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆