2013-04-24 61 views
2

我写了一个函数,它返回当前屏幕宽度为IO Integer(到目前为止)。在Haskell中连接字符串和IO整数

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”。我如何concat一个IO整数和一个普通的字符串?它是否与show一起使用?

任何人都可以帮助我吗?

+0

[Converting IO Int to Int]可能的重复(http://stackoverflow.com/questions/4235348/converting-io-int-to-int) – shang 2013-04-24 16:30:50

+0

不,它不是重复的。我不想将IO类型转换为非IO类型,我想用字符串连接IO Int。我知道如何连接一个字符串和一个整数,虽然...... 可悲的是,提到的解决方案并不适合我。我是否必须将字符串转换为IO字符串?然后concat IO String和IO Integer? – user2316484 2013-04-24 16:34:28

+0

@ user2316484如果你知道答案,你就知道答案。 – Carl 2013-04-24 17:05:03

回答

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 
1
magic_function :: IO Integer -> String -> IO String 
magic_function num msg = do 
          n <- num 
          return (msg ++ (show n)) 
0

我想你想要这样的:

magic :: IO Integer -> String -> IO String 
magic ios s = 
    do i <- ios 
    return $ s ++ ": " ++ (show i) 
1

建议的重复实际上给你所需要的答案,但我想,如果这是显而易见的,你怎么也不会首先会问这个。 :]

一般而言,您无法直接使用类型为IO something的值执行任何操作。这种类型不代表包装在IO中的something类型的值,而是可能使用IO的程序,该程序在执行时会生成something类型的值。毕竟,如果您不止一次使用IO something值,它可能与“某物”不同。

所以在你的情况下,你不能简单地连接String;您必须定义一个新的执行另一个程序的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将整数转换为String,然后像往常一样串接字符串。