我试图编译一个haskell游戏代码,这个代码生成三个线程,一个用于无限循环,一个用于收集用户的交互,一个用于触发事件。但是,代码无法编译,我不知道为什么。
以下是代码:
module Main where
import Control.Concurrent
import Control.Monad
import System.IO
import System.Random
import Text.Printf
data Msg = C Char | Time
data Event = C Char | Time Char
main :: IO ()
main = do
hSetBuffering stdout NoBuffering
hSetBuffering stdin NoBuffering
hSetEcho stdin False
-- shared resources
chan <- newEmptyMVar
removedDigits <- newEmptyMVar
unmatchedDigits <- newEmptyMVar
numberOfGuesses <- newEmptyMVar
--starting the generating thread and the user thread
forkIO $ generatingThread chan
forkIO $ userThread chan
--the main loop
if mainloop chan == True then "Congratulations! You won!" else "Better luck next time!"
return()
mainloop :: Chan c -> Bool
let mainloop = do
if length unmatchedDigits >= 10
then return False
Event <- readChan c
if Event == "timer"
then unmatchedDigits ++ param
else if testGuessedNumber param unmatchedDigits == True
then
removeMatchedDigit
if length unmatchedDigits == 0
then return True
mainloop c
-- Generating Thread aka event thread generating the random numbers
generatingThread :: Chan msgChan -> IO ()
generatingThread msgChan = forever $ do
publishTimerEvent msgChan 1000000
publishTimerEvent :: Chan msgChan -> Int delay ()
publishTimerEvent msgChan = do
c <- getRandomChar
putMVar msgChan ("timer" c)
threadDelay newDelay
velocity <- 0.9
if delay * velocity < 100
then newDelay <- 100
else newDelay <- delay * velocity
publishTimerEvent msgChan newDelay
getRandomChar :: Char c ()
getRandomChar = do
i <- randomRIO (0,9)
let c = "0123456789" !! i
return c
-- User Thread
userThread :: MVar Msg -> IO ()
userThread chan = forever $ do
c <- getChar
putMVar chan (C c)
showStr(show c)
testGuessedNumber :: Int -> Int -> Bool
testGuessedNumber a b
| a == b = True
| otherwise = False
-- Shows the given string at the left edge of the current terminal line after
-- having blanked out the first 20 characters on that line.
showStr :: String -> IO ()
showStr s = putStr ("\r" ++ replicate 20 ' ' ++ "\r" ++ s)
错误是“test.hs:36:3:错误:输入'事件'时解析错误”
答案 0 :(得分:1)
变量名称不能以大写字母开头,例如Event
。尝试将变量重命名为event
。
答案 1 :(得分:0)
在Haskell中,所有if ... then ... else
块必须包含所有组件;结果会是什么呢?
问题是编译器期待else
,但它实际上得到Event
。也就是说,您遇到的问题多于简单的解析错误。 return
不符合您的想法。例如,此代码将打印hi
。
main = do
return ()
putStrLn "hi"
return
函数只是将值提升为monad,它不会停止计算或类似的任何操作。以下是您可能想要的内容:
...
if length unmatchedDigits >= 10
then return False
else do
Event <- readChan c
if Event == "timer"
then ...
else ...
这样,在if块之后没有任何反应,所以函数就在那里结束,最后一个值为False
(如果是length unmatchedDigits >= 10
)或继续正确(如果length unmatchedDigits < 10
)
您几乎肯定不想使用Event
(大写E),因为这意味着它是一个数据构造函数。你可能意味着event
(小写e),它只是一个普通的变量名。
另外:这是非常非常非惯用的Haskell。你肯定在这种情况下不需要MVars,肯定不是其中的四个。 Chan
与MVar
不同,除非您正在执行重型多线程,否则您不需要任何一个。我高度建议您完全重写此内容,并尽量减少使用IO
的代码量(在此示例中可能是10-15行IO
代码,可能更小)。
这不是Java;您不需要在类型签名(Chan msgChan -> Int delay ()
)中命名变量,也不需要为标准库函数编写包装函数以使其类型单一化。 testGuessedNumber
与 (==)
完全相同。
如果您重新访问基本的纯函数语法并了解如何在Haskell中解决问题而不是尝试模拟另一种语言,那么您将获得更多成功。阅读一些LYAH或Real World Haskell。