Haskell: ошибка синтаксического анализа в программе ввода-вывода

Я пишу программу, чтобы помочь моему младшему брату выучить сложение. У меня нет опыта написания программ ввода-вывода, и я застрял с этой ошибкой синтаксического анализа:

MyCode.hs:6:25:
    Parse error in pattern: show
    Possibly caused by a missing 'do'?

Код:

mathExercise times (a,b) = 
    if times<=0
    then return ()
    else do let x = randInt a
            let y = randInt b 
            putStr (show x ++ " + "++ show y++ " = ")
            ans <- getInt
            if (ans==x+y)
            then do print True
                    mathExercise (times-1) (a,b)
            else do print False

person scholar guy    schedule 08.04.2015    source источник
comment
Не могли бы вы рассказать нам, какую ошибку вы видите?   -  person zcleghern    schedule 08.04.2015
comment
Я мог бы также сказать вам, что это не сработает. В Haskell нет функции randInt, которая работала бы так, как вы ожидаете. Изучите генерацию случайных чисел в Haskell или рассмотрите возможность использования другого языка для этой задачи.   -  person AJF    schedule 08.04.2015
comment
@AJFarmar ничего страшного, так как он уже в IO — просто используйте randomIO - к оператору: вы должны использовать это с чем-то вроде fmap (`mod` 10) randomIO, чтобы получить его в диапазоне ;)   -  person Random Dev    schedule 08.04.2015
comment
randInt — это функция, зависящая от времени.   -  person scholar guy    schedule 17.07.2016
comment
randomInt :: Integer -> IO Integer randomInt n = do time <- getCurrentTime return ( (rem` n) $ read $ take 6 $ formatTime defaultTimeLocale %q time) -- Извлечь случайное число из монады IO, небезопасно! randInt :: Integer -> Integer randInt = unsafePerformIO . randomInt`   -  person scholar guy    schedule 17.07.2016
comment
Код действительно сексуальный!   -  person scholar guy    schedule 17.07.2016


Ответы (2)


У вас смешанные вкладки и пробелы. В опубликованном вами коде есть вкладки в следующих местах (отмечены --->)

mathExercise times (a,b) = 
    if times<=0
--->then return ()
--->else do let x = randInt a
--->        let y = randInt b 
--->        putStr (show x ++ " + "++ show y++ " = ")
--->--->--->ans <- getInt
--->--->--->if (ans==x+y)
--->--->--->then do print True
--->--->--->--->--->mathExercise (times-1) (a,b)
--->--->--->else do print False

Предполагая, что существуют правильные объявления getInt и randInt, код будет скомпилирован с тем же макетом, если все вкладки заменены пробелами.

mathExercise times (a,b) = 
    if times<=0
    then return ()
    else do let x = randInt a
            let y = randInt b 
            putStr (show x ++ " + "++ show y++ " = ")
            ans <- getInt
            if (ans==x+y)
            then do print True
                    mathExercise (times-1) (a,b)
            else do print False

Если randInt на самом деле является случайным целым числом в IO, вместо этого вам нужно будет написать

mathExercise times (a,b) = 
    if times<=0
    then return ()
    else do x <- randInt a
            y <- randInt b
            ...

используя System.Random:

import System.Random (randomIO)

randInt a = fmap (`mod` a) randomIO

mathExercise times (a,b) = 
    if times<=0
    then return ()
    else do x <- randInt a
            y <- randInt b
            ...
person Cirdec    schedule 08.04.2015
comment
Я добавил одну возможную реализацию, используя randomIO Надеюсь, вы не возражаете - не стесняйтесь удалить ее снова, если это так. - person Random Dev; 08.04.2015
comment
@CarstenKönig Спасибо. Я собирался добавить еще один randInt a = randomRIO (1,a), но споткнулся об ужасное ограничение мономорфизма, когда определял getInt = readLn. - person Cirdec; 08.04.2015
comment
возможно, randomRIO даже лучше (вероятно, его легче понять, и ваши границы сдвинуты на 1, что может быть желательно) - если честно, я не помню, хотя, должно быть, просмотрел документы - так что спасибо за напоминание;) - person Random Dev; 08.04.2015

Проблема заключается в отступе оператора if и в том, что randInt является операцией ввода-вывода:

mathExercise times (a,b) = 
    if times<=0
    then return ()
    else do x <- randInt a
            y <- randInt b 
            putStr (show x ++ " + "++ show y++ " = ")
            ans <- getInt
            if (ans==x+y)
               then do print True
                       mathExercise (times-1) (a,b)
               else do print False
            -- ^ Indented here
person felipez    schedule 08.04.2015
comment
Это действительно. А теперь попробуйте сделать чистую функцию randInt! :П - person AJF; 08.04.2015
comment
извините, я не был уверен, что должен делать randInt - person felipez; 08.04.2015
comment
randomInt n = do time ‹- getCurrentTime return ( (rem n) $ read $ take 6 $ formatTime defaultTimeLocale %q time) -- Небезопасно извлечь случайное число из монады IO! randInt :: Integer -> Integer randInt = unsafePerformIO . randomInt - person scholar guy; 17.07.2016