如何在Haskell中将main :: IO()重写为由一个main :: IO()组成的两个函数

问题描述 投票:-1回答:2

我想通过拆分一些东西来使这个更简单的主要功能。但是当我添加一个新函数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"]
function haskell url-rewriting let
2个回答
2
投票

你已经做好了一切;缩进只是一个小问题。尝试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)

看看在我的版本中,eindstandputStrLn在它们之前有多少个空格?在你的版本中,putStrLn在它之前有一个额外的空间,导致GHC认为它是spelSpelen的参数。如果删除多余的空间,它应该开始工作。


1
投票

这个Q&A可能更适合codereview.stackexchange.com

除了基本的压痕问题,想要将main分成多个部分是一个好主意。

此外,你会想尝试使这些部分非IO。例如,应该可以在不触及任何IO的情况下解决所有游戏逻辑。如果您的游戏逻辑中没有任何getLineputStrLn调用,则测试更容易,并且几乎没有错误来源,因为输入验证可以分离到自己的部分。

至于游戏逻辑在没有嵌入IO的情况下可能会是什么样子,我不能说,因为游戏逻辑是用什么写的,荷兰人?如果您将此代码翻译为英语,或者将代码的翻译副本重新提交到codereview.stackexchange.com,则可能有人建议如何执行此操作。

© www.soinside.com 2019 - 2024. All rights reserved.