这是一个程序,以便GHC从用户获取数字n,然后它形成n个数字的列表,这些数字再次由用户给出。此代码显示循环的一些解析错误。我该如何删除该错误?
import System.IO
main = do
putStrLn "Please enter the number"
number <- readLn :: IO Int
putStrLn $ "The num is:" ++ show number
loop number
xs <- sequence [readLn :: IO Int]
putStrLn xs
loop:: Int -> IO ()
loop n = if 0==n then return () else return loop (n-1)
答案 0 :(得分:2)
除了其他答案所说的:
您不需要编写循环函数。
import System.IO
main = do
putStrLn "Please enter the number"
number <- readLn :: IO Int
putStrLn $ "The num is:" ++ show number
xs <- sequence (replicate number (readLn :: IO Int)) -- pay attention to this line
print xs
所以我们从readLn
开始。 replicate
列出了number
readLn
个。 (根据您的观点,您可能认为这是一个聪明的位。)
聪明的位:sequence
获取IO操作列表,并将其转换为一个大的IO操作。每个readLn
依次发生,收集返回值并在列表中返回。
答案 1 :(得分:0)
您的代码中有三个错误。复制并在GHC中启动它会显示以下消息:
temp.hs:9:13
Couldn't match expected type `Char' with actual type `Int'
Expected type: String
Actual type: [Int]
In the first argument of `putStrLn', namely `xs'
In the expression: putStrLn xs
这个很清楚。 putStrLn
需要String
,但xs
是Int
的列表。因此,只需使用print xs
代替putStrLn xs
即可解决问题(print = putStrLn . show
)。
接下来的两个实际上是关于同样的问题:
temp.hs:13:38:
No instance for (Monad ((->) t0))
arising from a use of `return'
Possible fix: add an instance declaration for (Monad ((->) t0))
In the expression: return loop (n - 1)
In the expression:
if 0 == n then return () else return loop (n - 1)
In an equation for `loop':
loop n = if 0 == n then return () else return loop (n - 1)
temp.hs:13:45:
Couldn't match expected type `IO ()'
with actual type `Int -> IO ()'
In the first argument of `return', namely `loop'
In the expression: return loop (n - 1)
In the expression:
if 0 == n then return () else return loop (n - 1)
问题在于类型。 loop
的类型为Int -> IO ()
。所以函数的第一个分支是正常的,因为你return ()
。但是,在else分支中,您返回的内容完全不同,因为return
不是语言的内置语句,而是正常函数。因此return loop (n - 1)
首先将您的loop
函数提升为monad,然后将其应用于(n - 1)
。
相反,你想要的是:
loop n = if n == 0 then return () else loop (n - 1)
另请注意,在Haskell中不需要0 == n
,因为没有办法意外地使用赋值而不是相等比较(它不会编译)。
编辑:正如其他答案指出的那样,loop
并没有真正做任何事情 - 它只调用自己n-1次然后返回()。
答案 2 :(得分:0)
如果我理解你的意图,你的意思是创建一个“循环”结构,它将执行 n 次动作,并生成一个结果列表。在您拥有的代码中,
loop number
xs <- sequence [readLn :: IO Int]
但这两个陈述是分开的;您需要发送您希望重复的行动到loop
作为inut:
xs <- loop number readLn :: IO [Int]
当然,您需要重写loop
以接受操作作为参数
loop :: Int -> IO a -> IO [a]
loop 0 action = return [] -- don't perform the action
loop n action = do
x <- action -- perform the action once
xs <- loop (n-1) action -- then perform it (n-1) times
return (x:xs) -- produce the resultant list
这里我用模式匹配编写了它,而不是if n == 0
。我可以用“if”结构轻松地编写它,但我个人倾向于发现那些相当丑陋。
但是等等,标准库中可能存在类似的东西。停止...... Hoogle时间!为新loop
a -> IO a -> IO [a]提供类型签名,我们发现replicateM
。
xs <- replicateM number readLn :: IO [Int]