我编写了一个函数,将当前屏幕宽度返回为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 ? ...
我想将魔术函数传递给一个字符串,比如“Screen Width:”,我希望它添加当前的屏幕宽度,这样我就可以得到“Screen Width:1680”。如何连接IO整数和常用字符串?它适用于show
吗?
有人可以帮我吗?
答案 0 :(得分: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 :(得分:2)
magic_function :: IO Integer -> String -> IO String
magic_function num msg = do
n <- num
return (msg ++ (show n))
答案 2 :(得分:2)
建议的重复确实实际上给出了你需要的答案,但我想如果你不明白你怎么不首先问这个问题。 :
通常,您不能直接使用类型为IO something
的值执行任何操作。此类型不是something
中包含的IO
类型的值,而是可能使用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
,然后像往常一样连接字符串。
答案 3 :(得分:1)
我想你想要这个:
magic :: IO Integer -> String -> IO String
magic ios s =
do i <- ios
return $ s ++ ": " ++ (show i)