3

我编写了一个函数,将当前屏幕宽度返回为 IO Integer(到目前为止工作)。

getScreenWidth:: IO Integer
getScreenWidth = do
                    (sx, sy, w, h) <- getScreenDim 0
                    return $ sx

现在我想将屏幕宽度添加到字符串中:

> magic_function :: IO Integer -> String -> ... magic output type
> magic_function = ... ? this is where i am stack at ? ...

我想将魔术函数传递给一个字符串,例如“屏幕宽度:”,并且我希望它添加当前屏幕宽度,以便获得“屏幕宽度:1680”。如何连接 IO 整数和通用字符串?它适用于show吗?

有人可以帮我吗?

4

4 回答 4

5

首先,忘记 IO:

labelInteger :: String -> Integer -> String
labelInteger label number = label ++ ": " ++ show number

现在担心 IO:

import Control.Monad (liftM, liftM2)

labelIOInteger :: String -> IO Integer -> IO String
labelIOInteger label ioNumber = liftM (labelInteger label) ioNumber

用作例如labelIOInteger "Screen Width" getScreenWidth...但要小心!如果你做这样的事情:

widthLabel <- labelIOInteger "Screen width" getScreenWidth
isPortrait <- liftM2 (<) getScreenWidth getScreenHeight

...然后getScreenWidth将被执行两次...诚然,对于这个特定的动作来说这不太可能是一个问题,但如果它是一个从文件、数据库或网站读取整数的动作,你可以看到执行它两次可能是不可取的。

通常最好不要编写类似的函数labelIOInteger,而是这样做:

widthLabel <- liftM (labelInteger "Screen Width") getScreenWidth

...因此,如果您发现自己需要将返回值用于两个不同的计算,您可以轻松地重构为:

screenWidth <- getScreenWidth
let widthLabel = labelInteger "Screen Width" screenWidth
isPortrait <- liftM (screenWidth <) getScreenHeight
于 2013-04-24T16:58:21.863 回答
2
magic_function :: IO Integer -> String -> IO String
magic_function num msg = do
                            n <- num
                            return (msg ++ (show n))
于 2013-04-24T16:55:48.063 回答
2

建议的副本实际上确实给出了您需要的答案,但我想如果很明显您不会一开始就问这个问题。:]

通常,您不能直接对类型为 的值执行任何操作IO something。此类型表示的不是something包裹在 中的类型值IO,而是可能使用的过程,该过程在执行时IO会产生类型值。毕竟,如果您多次something使用该值,它可能是不同的“东西” 。IO something

所以在你的情况下,你不能简单地连接Stringon; 您必须定义一个新IO过程来执行另一个过程,然后连接它产生的值。一般形式如下所示:

someFunction :: a -> b -> c
someFunction a b = ...

someProcedure :: IO a -> b -> IO c
someProcedure a b = do aValue <- a -- this executes "a"
                       return $ someFunction aValue b

有更短的方法来写它,但我认为它会帮助把它拼出来。当然,具体情况取决于您实际在做什么——对于您的程序,您可以使用show将整数转换为 a String,然后像往常一样连接字符串。

于 2013-04-24T16:58:47.613 回答
1

我想你想要这个:

magic :: IO Integer -> String -> IO String
magic ios s =
  do i <- ios
     return $ s ++ ": " ++ (show i)
于 2013-04-24T16:56:31.933 回答