Jam*_*ood 1 haskell syntax-error
我有这个代码:
module BalancedTwoDozenMultDrill where
import BalancedTwoDozenLib
myRandoms :: Int -> IO [Int]
myRandoms n = let x = 24^n `div` 2 in randomRs (-x,x) <$> getStdGen
drill :: [Int] -> IO ()
drill (x:y:rs) = do
putStr $ showInt x ++ " × " ++ showInt y ++ " = "
a <- getLine
case a of
"" -> return ()
showInt (x * y) -> do -- <= here
putStrLn "Correct"
drill rs
_ -> do
putStrLn $ "Wrong; " ++ showInt (x * y)
drill rs
main :: IO [Int]
main = drill =<< myRandoms =<< readLn
Run Code Online (Sandbox Code Playgroud)
并得到错误:
BalancedTwoDozenMultDrill.hs:11:18: Parse error in pattern: x * y
Run Code Online (Sandbox Code Playgroud)
但是,用以下内容替换部分case语句:
-- ...stuff
let i = showInt (x * y)
case a of
"" -> return ()
i -> do
-- stuff...
Run Code Online (Sandbox Code Playgroud)
使其解析(它转到"不在范围内"错误,我可以修复).我看到第一个片段错误的唯一原因是有功能应用正在进行中.在case语句中我不能使用普通函数应用程序来替代它吗?
如果在case语句中有模式,则必须遵循与函数参数模式匹配相同的规则.只能_匹配文字,构造函数和通配符,而不能匹配函数应用程序.相反,你可以做更多的事情
a <- getLine
let xyStr = showInt (x * y) -- Avoid recomputation with a let binding
when (not $ null a) $ do
if a == xyStr
then do
putStrLn "Correct"
drill rs
else do
putStrLn $ "Wrong; " ++ xyStr
drill rs
Run Code Online (Sandbox Code Playgroud)
你需要导入when从Control.Monad,虽然.
你必须在case语句中遵循与函数定义中的模式匹配相同的规则的原因是因为编译器实际上转换了像
head :: [a] -> a
head (x:xs) = x
head _ = error "Prelude.head: empty list"
Run Code Online (Sandbox Code Playgroud)
成
head :: [a] -> a
head list = case list of
(x:xs) -> x
_ -> error "Prelude.head: empty list"
Run Code Online (Sandbox Code Playgroud)
我们拥有前一版本的唯一原因是方便,它通常会使代码看起来更漂亮.
此链接应该能够为您提供有关什么是有效模式匹配结构的更全面的解释.
你遇到的另一个问题是试图showInt (x * y)用i哪里替换let i = showInt (x * y).执行此操作时,首先将值绑定showInt (x * y)到名称i,然后在case语句中使用模式
"" -> ...
i -> ...
_ -> ...
Run Code Online (Sandbox Code Playgroud)
所以现在你的模式是i,它将在之后表现得像一个包罗万象的模式"".这将重新绑定该icase语句范围的名称.
要记住的一个好规则是,您不能对运行时获得的值进行模式匹配,您必须检查相等或其他比较操作.