2017-03-26 25 views
1

私はハスケルを勉強しており、割り当てのためには、ヘビとはしごのゲームを印刷しなければなりません。始めて、私はボードを印刷しようとしており、これは私がやったことです。1つの関数で複数のステートメントを実行するにはどうすればよいですか?

import Data.List 
aRow :: Int -> String 
aRow n = "+" ++ take (4*n) (intercalate "" (repeat "---+")) ++ "\n|" ++  take (4*n) (intercalate "" (repeat " |")) ++ "\n" 

board :: Int -> Int -> IO() 
board 1 y = putStrLn (aRow y) 

私はそれは私が、私はちょうどこのような複数の文を呼び出すことはできませんが、誰もがに関するいくつかの洞察を提供することができることを知っている引数xとy

board x y = putStrLn (aRow y) 
      board (x-1) y 

を取るようなボードの別のインスタンスをしたいと思います私はこれと一緒に行くことができますか?私は引数 'y'を使ってaRowを呼び出し、それを 'x'回したいと思います。

ありがとうございました。また

:私はボード1 Y呼び出すとき、私は出力としてこれを取得: ボード1 5
+ --- + --- + --- + --- + --- +
|       |     |     |       |     |

答えて

7

私はもっともクリーンな方法は、IOを実行せずにボードを作成し、最後にIOを使用してプリントアウトすることだと思います。

あなたはこれを達成するためにconcatreplicateを使用することができます。

board :: Int -> Int -> String 
board x y = concat (replicate y (aRow x)) 

おそらく、一番下の行が欠落しているが、私はあなたがこれを理解しましょうよ!ところで

は、take (4*n) (intercalate "" (repeat "---+"))はそうあなたにaRowを書くことができconcat (replicate n "---+")と同じです:

aRow :: Int -> String 
aRow n = '+' : concat (replicate n "---+") 
     ++ "\n|" ++ concat (replicate n " |") 
     ++ "\n" 

編集

aRow :: Int -> String 
aRow n = unlines 
    [ '+' : concat (replicate n "---+") 
    , '|' : concat (replicate n " |") 
    ] 
:私は複数行にいくつかの String Sを連結する unlines :: [String] -> Stringを使用します
+0

私はあなたを見つけます。私はあなたを抱きしめます(「キュー・リアム・ニーソンの声」)。 – Cameron

2

IO()を実行し、さらに別のIO()アクションを実行します。一緒に彼らはIO()であるはずです。したがって、署名IO() -> IO() -> IO()のコンビネータを探しています。 ask Hoogle about thisすることができます...ああああ、それはかなり無関係の結果をかなり与える。しかし、またthe right one, namely

(>>) :: Monad m => m a -> m b -> m b 

あなたIO() -> IO() -> IO()m ~ IOa ~ b ~()を設定することにより得られ、この署名の特殊なケースです。だから、あなたは、がかなり頻繁にHaskellで使用されているこれらのモナドシング事業者なので、それは彼らのために特別な構文糖の構文を持っている、すなわち

board x y = do 
    putStrLn (aRow y) 
    board (x-1) y 

board x y = putStrLn (aRow y) 
     >> board (x-1) y 

を書くことができます[OK]をので、これは動作しますが、それは実際に慣用的ではありません。"反復変数" xを使用した手動再帰ループはむしろエラーが発生しやすくなります(最初の終了条件とステップ条件を正しく取得する必要があります)。実際には、あなたがしていることはすべて、の行に同じアクションx回を実行することです。だから、本当にあなたはInt -> IO() -> IO()に興味があります。再びask Hoogle;今回the right resultは少し早い...

replicateM_ :: Applicative m => Int -> m a -> m() 

ので

さらに良い
board :: Int -> Int -> IO() 
board x y = replicateM_ x $ putStrLn (aRow y) 

を起動した、ブーメラン発言として、IOが完全にループを回避することです。

2

あなたはちょうど2つのモナドの関数シーケンスする必要があります。

board x y = putStrLn (aRow y) >> board (x - 1) y 

または表記doとを

x == 0がより自然なベースケースになります。なお
board x y = do 
    putStrLn (aRow y) 
    board (x - 1) y 

board 0 y = return() 
board x y = do 
    putStrLn (aRow y) 
    board (x - 1) (aRow y) 

参照してください。フーを書くもっと慣れた方法のためのブーメランの答えしかし、

関連する問題