我编译了这段代码,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
...
答案 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