在Haskell中连接String和IO Integer

use*_*484 3 string io haskell integer concatenation

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

getScreenWidth:: IO Integer
getScreenWidth = do
                    (sx, sy, w, h) <- getScreenDim 0
                    return $ sx
Run Code Online (Sandbox Code Playgroud)

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

> magic_function :: IO Integer -> String -> ... magic output type
> magic_function = ... ? this is where i am stack at ? ...
Run Code Online (Sandbox Code Playgroud)

我想魔术函数传递一个字符串,像"屏幕宽度:"我希望它添加当前屏幕的宽度,使我得到"屏幕宽度:1680".如何连接IO Integer和常用String?它有用show吗?

有人可以帮我吗?

dav*_*420 5

首先,忘记IO:

labelInteger :: String -> Integer -> String
labelInteger label number = label ++ ": " ++ show number
Run Code Online (Sandbox Code Playgroud)

现在担心IO:

import Control.Monad (liftM, liftM2)

labelIOInteger :: String -> IO Integer -> IO String
labelIOInteger label ioNumber = liftM (labelInteger label) ioNumber
Run Code Online (Sandbox Code Playgroud)

用作例如labelIOInteger "Screen Width" getScreenWidth......但要注意!如果您这样做:

widthLabel <- labelIOInteger "Screen width" getScreenWidth
isPortrait <- liftM2 (<) getScreenWidth getScreenHeight
Run Code Online (Sandbox Code Playgroud)

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

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

widthLabel <- liftM (labelInteger "Screen Width") getScreenWidth
Run Code Online (Sandbox Code Playgroud)

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

screenWidth <- getScreenWidth
let widthLabel = labelInteger "Screen Width" screenWidth
isPortrait <- liftM (screenWidth <) getScreenHeight
Run Code Online (Sandbox Code Playgroud)