Haskell解析错误:"可能是错误的缩进或括号不匹配"

时间:2014-11-28 03:31:42

标签: haskell

我编译了这段代码,ghc告诉我"解析错误(可能是错误的缩进或括号不匹配)"在最后一行(" randSeq :: Integer - > String")

pair = randSeq n ++ " | " ++ randSeq n where do g <- newStdGen
                                             let n = randomR (1,10) g

randSeq :: Integer -> String
...

我确保使用空格来缩进。我避免使用&#39; let&#39;关键字如下,但它仍然会产生相同的错误

pair = randSeq n ++ " | " ++ randSeq n where n = randomR (1,10) g
                                             do g <- newSTdGen

randSeq :: Integer -> String
...

2 个答案:

答案 0 :(得分:4)

where用于将变量绑定到新值,如

f x = ....
  where n = ...
        m = ...
        g y = ...

特别是,无法运行IO操作的地方:最多可以定义例如: m是这样的行动。 Haskell类型系统基本上强制您指定IO操作之间的顺序,通常使用do完成。如果Haskell允许where do g <- ...,则不清楚何时对其他操作执行此操作:例如,

f x = do print 1
         print 2
         print n
         print 4
  where n <- do print "hello!"    -- hypothetical Haskell syntax
                return 3

可能意味着

f x = do print 1
         n <- do print "hello!"
                 return 3
         print 2
         print n
         print 4

以及

f x = do print 1
         print 2
         n <- do print "hello!"
                 return 3
         print n
         print 4

回到您的代码,您只需将其更改为单个do

即可
pair :: IO String
pair = do g <- newSTdGen
          let n = randomR (1,10) g
          return (randSeq n ++ " | " ++ randSeq n)

顺便说一下,库函数randomRIO执行相同的数字生成,所以你可以简单地使用

pair :: IO String
pair = do n <- randomRIO (1,10)
          return (randSeq n ++ " | " ++ randSeq n)

请记住,上面会生成一个随机数,并使用它两次。如果您打算使用两个独立的随机数,请改用

pair :: IO String
pair = do n1 <- randomRIO (1,10)
          n2 <- randomRIO (1,10)
          return (randSeq n1 ++ " | " ++ randSeq n2)

最后,上面的代码假定randSeq返回String而不是IO String。如果它确实返回IO String,您还必须订购这两个操作。

pair :: IO String
pair = do n1 <- randomRIO (1,10)
          n2 <- randomRIO (1,10)
          s1 <- randSeq n1
          s2 <- randSeq n2
          return (s1 ++ " | " ++ s2)

或者,使用一些库函数来稍微美化代码,

pair :: IO String
pair = do s1 <- randomRIO (1,10) >>= randSeq
          s2 <- randomRIO (1,10) >>= randSeq
          return (s1 ++ " | " ++ s2)

甚至

pair :: IO String
pair = do s1 <- randomSeq
          s2 <- randomSeq
          return (s1 ++ " | " ++ s2)
   where -- this does not run the IO action, it only gives it a name
         randomSeq = randomRIO (1,10) >>= randSeq

最后,pair在没有String monad的情况下无法返回IO,因为它不是常量字符串,而是每次运行时生成随机字符串的操作。

答案 1 :(得分:1)

do之后您无法使用where关键字。这应该可以帮助你:

randSeq :: Integer -> String
randSeq n = undefined -- I don't know how it is implemented

{- To obtain random number: -} 
randInteger :: IO Integer
randInteger =
  newStdGen >>=
    return . fst . randomR (0, 10)

pair :: IO String   
pair = randInteger >>= \ n ->
         let rs = randSeq n in
           return $ rs ++ " | " ++ rs