来自IO的矩阵转置

时间:2011-12-21 14:20:23

标签: haskell

我有一个问题,用户输入数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 ??

2 个答案:

答案 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 <- barlet foo = bar之间的区别在于前者提取IO计算的结果,而后者只给出了值的名称。

基本上,答案是你不需要将任何放入 IO来执行此操作,因为创建IO操作以执行诸如打印字符串输出等操作的所有函数都需要值。但是,这并不限于打印完全纯计算的结果,因为您可以从先前的IO计算中提取值,然后将它们作为纯值提供给打印函数。 (事实上​​,这是monad的本质,为什么Haskell首先使用它们来模拟IO!)

答案 1 :(得分:0)

完全可以完全按照您的要求进行操作,但有时候制作字符串然后打印它会更容易一些。在这种情况下,它实际上非常容易。您需要知道的只有两个函数wordslines,以及它们的倒数unwordsunlines

以下是您的问题的可能解决方案(请注意,我不检查输入是否为整数,并且我使用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和它的逆行之间。