[英]How to rewrite in Haskell a main :: IO () to two functions consisting of one main :: IO()
我想通过拆分一些东西使它成为一个更简单的主要功能。 但是,当我添加新功能maakNieuwSpel时,出现错误
maakNieuwSpel :: Int -> String -> IO ()
maakNieuwSpel aantal firstName= do let rijTegels = volleRijTegels
let spelers = deSpelers aantal firstName
w <- spelSpelen rijTegels spelers 0
putStrLn (w ++ "dit is waar ik mee bezig was in functie nieuwSpel")
当我主要用
eindstand <- maakNieuwSpel (digitToInt aantalTegenspelers) firstName
它给了错误。
我尝试并希望实现的另一件事是通过放置where函数来重写main中的let函数。 我当时就是这样想的
eindstand <- spelSpelen rijTegels spelers 0
where rijTegels = volleRijTegels
spelers = deSpelers (digitToInt aantalTegenspelers) firstName
但是然后它说“解析输入'='时的错误也许您需要在'do'块中添加'let'吗?”
这是我的代码的一部分。 我想它将为您提供我正在做的事情的足够洞察力。
data Dobbelsteen = Steen Char -- now its values can be specified
deriving (Show, Eq)
data Tegel = Teg Int Int
deriving (Show, Eq)
data Speler = Spel Tactiek Spelersstapel String
type Tactiek = ([Dobbelsteen] -> [Dobbelsteen] -> IO [Dobbelsteen], [Dobbelsteen] -> Int -> IO Bool)
type Spelersstapel = [Tegel]
main :: IO ()
main = do putStrLn ("Hoi! Je speelt regenwormen. Wat is je naam?")
firstName <- getLine
putStrLn ("Beste "++ firstName ++ ", je speelt tegen twee computertegenstanders. Ze heten Lap en Top.")
putStr "Tegen hoeveel computertegenstanders wil u spelen? (Dit spel is voor 2 tot 8 personen) "
aantalTegenspelers <- getChar
let rijTegels = volleRijTegels
let spelers = deSpelers (digitToInt aantalTegenspelers) firstName
eindstand <- {-maakNieuwSpel (digitToInt aantalTegenspelers) firstName-} spelSpelen rijTegels spelers 0
putStrLn ("Het spel is afgelopen. De eindstand is " ++ eindstand)
spelSpelen :: [Tegel] -> [Speler] -> Int -> IO String -- de RijTegels, de spelers en degene die gaat spelen (int)
spelSpelen [] spelers spelerNr = do return (show (bepaalEindStand spelers))
spelSpelen rijTegels spelers spelerNr = do let Spel tactiek stapel naam = (spelers !! spelerNr)
putStrLn ("Deze speler is nu aan de beurt: " ++ naam)
score <- beurt tactiek (\x -> elem x (bepaalGeldigeScore spelers naam rijTegels))
let rijTegelsNieuw = pakTegelAlsMogelijk rijTegels score
let rijTegelsTeruggelegdNieuw = legTegelTerug spelers rijTegels score
let spelersAfgepaktNieuw = pakTegelAf spelers score
let spelersNieuw = voegTegelToeAanSpelerVanStapel spelersAfgepaktNieuw score naam rijTegelsTeruggelegdNieuw
putStrLn ("De beurt van speler " ++ naam ++ " is nu afgelopen.")
printStatus rijTegelsNieuw spelersNieuw
spelSpelen rijTegelsNieuw spelersNieuw ( (spelerNr+1) `mod` 3)
volleRijTegels :: [Tegel] -- deze functie maakt de rij tegels van 21 tot 36.
volleRijTegels = zipWith Teg [21..36] (replicate 4 1 ++ replicate 4 2 ++ replicate 4 3 ++ replicate 4 4)
deSpelers :: Int -> String -> [Speler]
deSpelers aantalTegenspelers firstName = do [Spel computerTactiek [] firstName, Spel computerTactiek [] "Lap", Spel computerTactiek [] "Top"]
您已正确完成所有操作; 缩进只是一个小问题。 尝试dedenting的最后一行main
,就像这样:
main :: IO ()
main = do
-- ... stuff ...
eindstand <- {-maakNieuwSpel (digitToInt aantalTegenspelers) firstName-} spelSpelen rijTegels spelers 0
putStrLn ("Het spel is afgelopen. De eindstand is " ++ eindstand)
看看在我的版本中, eindstand
和putStrLn
有多少空格? 在您的版本中, putStrLn
有多余的空间,导致GHC认为这是spelSpelen
的参数。 如果您删除了多余的空间,它将开始工作。
该问答可能更适合codereview.stackexchange.com 。
除了基本的缩进问题之外,想要将main
分成多个部分也是一个好主意。
另外,您将要尝试使某些部分变为非IO
。 例如,应该有可能在不接触任何IO
情况下解决所有游戏逻辑。 如果您的游戏逻辑中没有任何getLine
或putStrLn
调用,则它更容易测试,并且错误源少,因为输入验证可以分为独立的部分。
至于没有嵌入IO
的游戏逻辑的样子,我不能说,因为游戏逻辑是用荷兰语写的? 如果您将此代码翻译成英语,或将代码的翻译副本重新提交到codereview.stackexchange.com,则有人可能会建议如何执行此操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.