atl*_*tis 3 monads haskell map
我正在操作的地图具有monadic键(类型IO Double
).我需要findMax
在这张地图上使用.我可以用liftM
它吗?
Map.findMax $ Map.fromList [(f x, "X"), (f y, "Y"), (f z, "Z")]
Run Code Online (Sandbox Code Playgroud)
这里f x
有类型IO Double
.
将IO
-typed值作为映射中的键是没有意义的.IO t
某种类型的类型值t
可以被认为是一个"程序",t
每次运行时都会生成一个类型的值:您可以多次运行它,每次它可以生成不同的值.
所以,想要你可能想要的是先运行"程序"来获得一些结果; 这些结果可以成为地图的关键.
例如,如果你有一个"程序"
f :: Int -> IO Int
Run Code Online (Sandbox Code Playgroud)
这需要整数和计算,可能有效,整数,你需要运行输入[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
Run Code Online (Sandbox Code Playgroud)
这假定值是通过函数从键计算的
g :: Int -> Int
Run Code Online (Sandbox Code Playgroud)
createMap
生成从整数到整数的映射; 它在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))
Run Code Online (Sandbox Code Playgroud)
当然,地图不需要一次创建,但也可以逐步构建:
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
Run Code Online (Sandbox Code Playgroud)
您应该在插入地图之前执行monadic操作,如下所示:
insertValue :: Value -> Map Key Value -> IO (Map Key Value)
insertValue value m = do
key <- calculateKey value
return $ Map.insert key value m
Run Code Online (Sandbox Code Playgroud)
哪里
calculateKey :: Value -> IO Key
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1358 次 |
最近记录: |