如何在功能组合中打印中间结果

时间:2020-03-28 19:30:43

标签: haskell

(完整的代码在问题的结尾。)

我正在尝试打印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章中

https://www.cs.nott.ac.uk/~pszgmh/pih.html

1 个答案:

答案 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 ","   |   |   "]
 λ> 

相关问题