为什么这个haskell代码无法编译

时间:2017-04-04 19:04:55

标签: haskell

我试图编译一个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:错误:输入'事件'时解析错误”

2 个答案:

答案 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,肯定不是其中的四个。 ChanMVar不同,除非您正在执行重型多线程,否则您不需要任何一个。我高度建议您完全重写此内容,并尽量减少使用IO的代码量(在此示例中可能是10-15行IO代码,可能更小)。

这不是Java;您不需要在类型签名(Chan msgChan -> Int delay ())中命名变量,也不需要为标准库函数编写包装函数以使其类型单一化。 testGuessedNumber (==)完全相同。

如果您重新访问基本的纯函数语法并了解如何在Haskell中解决问题而不是尝试模拟另一种语言,那么您将获得更多成功。阅读一些LYAHReal World Haskell