(完整的代码在问题的结尾。)
我正在尝试打印showRow
而不包含beside
的中间结果
首先将这段代码加载到ghci中:
-- Tic-tac-toe example from chapter 11 of Programming in Haskell,
-- Graham Hutton, Cambridge University Press, 2016.
-- Basic declarations
import Data.Char
import Data.List
import System.IO
size :: Int
size = 3
type Grid = [[Player]]
data Player = O | B | X
deriving (Eq, Ord, Show)
grid :: Grid
grid = [[B,O,O],[O,X,O],[X,X,X]]
next :: Player -> Player
next O = X
next B = B
next X = O
-- Grid utilities
empty :: Grid
empty = replicate size (replicate size B)
full :: Grid -> Bool
full = all (/= B) . concat
turn :: Grid -> Player
turn g = if os <= xs then O else X
where
os = length (filter (== O) ps)
xs = length (filter (== X) ps)
ps = concat g
wins :: Player -> Grid -> Bool
wins p g = any line (rows ++ cols ++ dias)
where
line = all (== p)
rows = g
cols = transpose g
dias = [diag g, diag (map reverse g)]
diag :: Grid -> [Player]
diag g = [g !! n !! n | n <- [0..size-1]]
won :: Grid -> Bool
won g = wins O g || wins X g
-- Displaying a grid
putGrid :: Grid -> IO ()
putGrid =
putStrLn . unlines . concat . interleave bar . map showRow
where bar = [replicate ((size*4)-1) '-']
showRow :: [Player] -> [String]
showRow = beside . interleave bar . map showPlayer
where
beside = foldr1 (zipWith (++))
bar = replicate 3 "|"
showPlayer :: Player -> [String]
showPlayer O = [" ", " O ", " "]
showPlayer B = [" ", " ", " "]
showPlayer X = [" ", " X ", " "]
interleave :: a -> [a] -> [a]
interleave x [] = []
interleave x [y] = [y]
interleave x (y:ys) = y : x : interleave x ys
showRow row
正在工作:
*Main> row = grid !! 0
*Main> showRow row
[" | | "," | O | O "," | | "]
但不是以下内容:
*Main> row = grid !! 0
*Main> (interleave replicate 3 "|") . (map showPlayer row)
<interactive>:9:2: error:
• Couldn't match expected type ‘[Char] -> b0 -> c’
with actual type ‘[Int -> a0 -> [a0]]’
• The function ‘interleave’ is applied to three arguments,
but its type ‘(Int -> a0 -> [a0])
-> [Int -> a0 -> [a0]] -> [Int -> a0 -> [a0]]’
has only two
In the first argument of ‘(.)’, namely
‘(interleave replicate 3 "|")’
In the expression:
(interleave replicate 3 "|") . (map showPlayer row)
• Relevant bindings include
it :: a -> c (bound at <interactive>:9:1)
<interactive>:9:33: error:
• Couldn't match expected type ‘a -> b0’
with actual type ‘[[String]]’
• Possible cause: ‘map’ is applied to too many arguments
In the second argument of ‘(.)’, namely ‘(map showPlayer row)’
In the expression:
(interleave replicate 3 "|") . (map showPlayer row)
In an equation for ‘it’:
it = (interleave replicate 3 "|") . (map showPlayer row)
• Relevant bindings include
it :: a -> c (bound at <interactive>:9:1)
您需要加载到ghci中的代码也在以下第11章中
答案 0 :(得分:3)
我正在尝试打印showRow的中间结果
记住美元和括号:
λ>
λ> (interleave $ replicate 3 "|") $ (map showPlayer row)
[[" "," "," "],["|","|","|"],[" "," O "," "],["|","|","|"],[" "," O "," "]]
λ>
λ> interleave (replicate 3 "|") (map showPlayer row)
[[" "," "," "],["|","|","|"],[" "," O "," "],["|","|","|"],[" "," O "," "]]
λ>
很长的解释:您的初始表达式(interleave replicate 3 "|") . (map showPlayer row)
使用了点/句点函数组合运算符,即“。”。在Haskell源代码中,在数学文本中为“·”或“∘”。仅当(map showPlayer row)
是可组合的,即某种 function 时,此方法才有效。但是该表达式是类型[[String]]
的值表达式。因此,它不是函数,因此无法组成。这是冗长且不必要的编译器错误消息想要告诉您的。
更一般地说,在命令式编程圈中,也许可以使用Haskell来实现“ àla printf()调试样式”。
您需要:
import Debug.Trace
通过trace
的特殊特权,功能可以在stderr上打印内容,同时保持在IO monad之外。表达式trace debugMsg xyz
的计算结果仅为xyz。
您可以像这样重写showRow
函数:
showRow1 :: [Player] -> [String]
showRow1 players = let beside = foldr1 (zipWith (++))
bar = replicate 3 "|"
res1 = map showPlayer players
res2nd = interleave bar res1 -- no debug
msg = "Trace: res2 = " ++ show res2nd
res2 = trace msg res2nd
in beside res2
在ghci下测试:
λ>
λ> showRow $ [O,B,X]
[" | | "," O | | X "," | | "]
λ>
λ> showRow1 $ [O,B,X]
Trace: res2 = [[" "," O "," "],["|","|","|"],[" "," "," "],["|","|","|"],[" "," X "," "]]
[" | | "," O | | X "," | | "]
λ>