我试图在Haskell中编写游戏nim,但有些东西不起作用,我不知道为什么。 我有2个函数getRow和getNumber(它们都使用getInt,我也包括它),getRow以我想要的方式工作,但是使用getNumber我得到了sobe错误而且它不想加载。
getInt :: Int
getInt = do
s <- getLine
read s
getRow :: [Int] -> (Int,Int)
getRow board = do
putStrLn "Give me row number "
row <- getInt
if ((length board) > (row-1)) && ((board!!(row-1)) > 0 )
then (row, board!!(row-1))
else do putStrLn "niepoprawny rzad"
getRow board
getNumber :: [Int] -> (Int, Int) -> (Int, Int)
getNumber board row = do
putStrLn "Give me number of stones you want to take"
number <- getInt
if number < 1
then do putStrLn "wrong number"
getNumber board row
else if (number > (snd row))
then ((fst row), 0)
else ((fst row), ((snd row) - number))
在getNumber中我得到:
Couldn't match expected type '(Int, Int)' with actual type 'Int'
In a stmt of a 'do' block: number <- getInt"
我不了解任何一个。为什么getRow有效但getNumber没有?它们非常相似。
答案 0 :(得分:5)
此代码中存在许多普遍存在的错误。最特别的是,纯粹的计算是在do
块的最后一行完成的 - 这些必须return
,以便它们最终“在IO
”中。您的所有类型都没有在IO
monad中返回。 if
中的上一个getNumber
语句中可能还有缩进错误。
getInt :: IO Int -- in the IO monad
getInt = do
s <- getLine
return (read s) -- we must return pure values from monads
getRow :: [Int] -> IO (Int,Int) -- in the IO monad
getRow board = do
putStrLn "Give me row number "
row <- getInt
if ((length board) > (row-1)) && ((board!!(row-1)) > 0 )
then return (row, board!!(row-1)) -- we must return pure values from monads
else do putStrLn "niepoprawny rzad"
getRow board
getNumber :: [Int] -> (Int, Int) -> IO (Int, Int) -- in the IO monad
getNumber board row = do
putStrLn "Give me number of stones you want to take"
number <- getInt
if number < 1
then do putStrLn "wrong number"
getNumber board row
else if (number > (snd row)) -- better indentation
then return ((fst row), 0) -- we must return
else return ((fst row), ((snd row) - number)) -- we must return