LoginSignup
8
5

More than 3 years have passed since last update.

Haskellでオンラインジャッジに取り組むときの入出力(後編:標準出力への出し方)

Last updated at Posted at 2018-12-13

「Haskellは競技プログラミングには向いている」と言われたりもするが、競プロやオンラインジャッジにHaskellで取り組もうとすると、最初は問題を解くよりも、「どうやって入力を受けて、出力すれば良いのか?」の方が分からなかったりする。
そんなときのためのメモ。今回は結果の標準出力への出し方。(前編の入力編はこちら

前編で入力を処理可能なところまで変換した。

input.txt
3
10 20
30 40
50 60
sample6.hs
main = do
  _ : input <- lines <$> getContents
  print . map (map read . words) $ input
-- [[10,20],[30,40],[50,60]]

これを極々単純に各行の和をとって出力、とすると

sample7.hs
main = do
  _ : input <- lines <$> getContents
--let ans = map sum . map (map read . words) $ input
  let ans = map     (sum . map read . words) $ input
-- [30,70,110]
  print ans
  • 外側のリストの各要素をsumするためにmapする(要は行単位で処理をする関数がsumの場所にくる)
  • map f . map gmap (f.g)なので、このような形になる。
  • ここからが本題。出来あがった計算結果のリストを一つづつ改行して出力したい。
sample7.hs
main = do
  _ : input <- lines <$> getContents
  let result = map (sum . map read . words) $ input
-- [30,70,110]
  mapM_ print result
-- 30
-- 70
-- 110
  • リスト内の計算結果の出力には専らprintを使う
  • print :: Show a => a -> IO ()
  • printputStrLn.showであるのでshowできる型なら無条件に出力して改行してくれる
  • printを各要素に適用するにはmapではなくmapM_を使う。なぜならばprintはIOアクションを返すから
  • mapM_ :: (Monad m, Foldable t) => (a -> m b) -> t a -> m ()
  • ここでmIOtはリスト、aIntであるので、mapM_の型は(Int -> IO()) -> [Int] -> IO()となる
StringOutput.hs
print "OK"
--- "OK"
putStrLn "OK"
-- OK
  • ただし、出力する値がStringの場合printを使用するとダブルクォーテーションが付いてしまうので、この場合はputStrLnを使う
  • putStrLn :: String -> IO ()

forM

mapMと引数の順序が異なるのみで、それ以外は全く同じのforM
「すごいHaskellたのしく学ぼう!」では

forM.hs
main = do 
   colors <- forM [1,2,3,4] $ \a -> do 
     putStrLn $ "Which color do you associate with the number " ++ show a ++ "?"
     getLine 
   putStrLn "The colors that you associate with 1,2,3 and 4 are: "  
   mapM putStrLn colors

これはmapMで書くなら

mapM.hs
main = do 
   colors <- mapM f [1,2,3,4]
   putStrLn "The colors that you associate with 1,2,3 and 4 are: "  
   mapM putStrLn colors

f :: a -> IO String
f a =  do 
         putStrLn $ "Which color do you associate with the number " ++ show a ++ "?"
         getLine

実行結果はいずれも同じ。

result.txt
Which color do you associate with the number 1?
white
Which color do you associate with the number 2?
blue
Which color do you associate with the number 3?
red
Which color do you associate with the number 4?
orange
The colors that you associate with 1, 2, 3 and 4 are:
white
blue
red
orange 

「すごいH本」では訳注として「mapM と forM は関数とリスト、どちらの引数を長く書きたいかによって使い分けるのが良いでしょう。」と書かれている。
手続き的に引数に与える値を次々に変えては何かしたい、というようなときにはforMがしっくりくる場合もある。

8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5