我有一个问题,用户输入数m(意味着矩阵有m行,m列),然后从stdin读取矩阵。我想转置矩阵,然后以相同的格式将矩阵输出回屏幕 例如:
主>主要
3
1 2 3
4 5 6
7 8 9
1 4 7
2 5 8
3 6 9
无论如何,我到了中间位置,但我不知道如何将[[Int]]解析回IO,因此可以在屏幕上打印。
这是我的代码:
import Control.Monad (replicateM)
transpose :: [[a]]->[[a]]
transpose ([]:_) = []
transpose x = (map head x) : transpose (map tail x)
readMany :: Read a => IO [a]
readMany = fmap (map read . words) getLine
parse :: IO ([[Int]])
parse = do
[m] <- readMany
xss <- replicateM m readMany
let matrix = transpose xss
return (matrix)
main :: IO ()
main = do
parse
?? --
print ??
答案 0 :(得分:2)
首先,您必须提取您解析的值:
main :: IO ()
main = do
matrix <- parse
...
print ???
现在,print
的类型是什么?
print :: (Show a) => a -> IO ()
好吧,[[Int]]
是Show
的一个实例,因此我们可以将print视为其类型的特化:
print :: [[Int]] -> IO ()
所以,实际上,就像填写我们要打印的列表代替???
一样简单:
main :: IO ()
main = do
matrix <- parse
print matrix
但是,这会以与GHCi相同的方式打印数据。如果要以自定义格式打印数据,则需要:
putStr :: String -> IO ()
假设您编写了一个函数来将矩阵格式化为字符串格式:
formatMatrix :: [[Int]] -> String
这使得完整的程序:
main :: IO ()
main = do
matrix <- parse
putStr (formatMatrix matrix)
foo <- bar
和let foo = bar
之间的区别在于前者提取IO计算的结果,而后者只给出了值的名称。
基本上,答案是你不需要将任何放入 IO来执行此操作,因为创建IO操作以执行诸如打印字符串输出等操作的所有函数都需要纯值。但是,这并不限于打印完全纯计算的结果,因为您可以从先前的IO计算中提取值,然后将它们作为纯值提供给打印函数。 (事实上,这是monad的本质,为什么Haskell首先使用它们来模拟IO!)
答案 1 :(得分:0)
完全可以完全按照您的要求进行操作,但有时候制作字符串然后打印它会更容易一些。在这种情况下,它实际上非常容易。您需要知道的只有两个函数words
和lines
,以及它们的倒数unwords
和unlines
。
以下是您的问题的可能解决方案(请注意,我不检查输入是否为整数,并且我使用transpose
中的Data.List
import Data.List
import Control.Monad
main = do
n <- liftM read getLine
xs <- replicateM n getLine
putStrLn (unlines . map unwords . transpose . map words $ xs)
由于replicateM n getLine
为我们提供了一个行列表,lines
对整个输入做了什么,我们只是将transpose
夹在map words . lines
和它的逆行之间。