Как напечатать новую строку в Haskell?

Я пытался сделать игру Tic Tac Toe для ежемесячного учебника и написал этот код, чтобы сделать поле первым:

box :: [String]
box = ["0 | 1 | 2",
       "---------",
       "3 | 4 | 5",
       "---------",
       "6 | 7 | 8"]

Я получаю этот вывод в GHCi:

["0 | 1 | 2\n","---------\n","3 | 4 | 5\n","---------\n","6 | 7 | 8\n"]

Я хотел получить:

 0 | 1 | 2
 ---------
 3 | 4 | 5
 ---------
 6 | 7 | 8

Как я могу напечатать такую ​​сетку?

Ответ 1

Попробуйте что-то вроде:

box = unlines $ ["0 | 1 | 2",
                 "---------",
                 "3 | 4 | 5",
                 "---------",
                 "6 | 7 | 8"]

Затем выведите поле с помощью putStr:

main = putStr box

Что unlines делает, это взять список строк и объединить их вместе с использованием строк новой строки. Он в основном рассматривает список строк как список строк и превращает их в одну строку.

putStr просто печатает строку в STDOUT. Если вы использовали print или GHCi для просмотра строки вместо этого, символы новой строки будут отображаться как \n, а не фактические символы новой строки. Это происходит потому, что экземпляр show String предназначен для сериализации строки, как вы бы ее ввели, а не для ее печати. Оба print и GHCi используют show перед выходом в STDOUT.

Если вы находитесь в приглашении GHCi и хотите увидеть, как выглядит строка, вы можете напрямую использовать putStr:

*Main> putStr box
0 | 1 | 2
---------
3 | 4 | 5
---------
6 | 7 | 8
*Main>

Ответ 2

Другой подход -

main = mapM_ putStrLn box

mapM :: Monad m => (a -> m b) -> [a] -> m [b] является аналогом отображения, но для монадических функций его подчеркнутый двоюродный брат mapM_ :: Monad m => (a -> m b) -> [a] -> m () не собирает возвращаемые значения и поэтому может быть более эффективным. Если возвращаемые значения неинтересны, как для putStrLn s, mapM_ - лучший выбор.