Haskell中IO ()函数如何将let/in结构替换为where语法?
问题原因
你遇到的错误是作用域不匹配导致的,和是否为IO函数无关,是where子句和do块的绑定规则差异造成的:
where子句依附于当前的顶层函数定义,仅能访问函数入参、当前作用域顶层定义的变量,完全无法读取do块内部通过<-绑定的length、width变量。- do块内的
<-绑定是Monad>>=操作的语法糖,绑定的变量仅在当前do块的后续代码中生效,属于do块的内部局部作用域,层级低于where的作用域,因此where无法访问这些变量。
替代实现方案
你可以选择下面两种写法实现同等效果:
方案1:使用do块原生let语法
do块内的let可以省略in关键字,作用域自动覆盖后续所有do块代码,写法比你原来的let/in更简洁:
squareCalc :: IO () squareCalc = do putStrLn "Pease enter the lenght" length <- getLine putStrLn "Pleas enter the width" width <- getLine let square = read length * read width putStrLn ("The square is " ++ show square)
方案2:用where定义辅助函数传参调用
如果你确实想将计算逻辑拆分到where子句中,可以把计算逻辑封装为带参数的辅助函数,在do块内主动把length、width作为参数传入即可:
squareCalc2 :: IO () squareCalc2 = do putStrLn "Pease enter the lenght" length <- getLine putStrLn "Pleas enter the width" width <- getLine putStrLn ("The square is " ++ show (calcSquare length width)) where calcSquare l w = read l * read w
内容的提问来源于stack exchange,提问作者Evgeniy Tishin
相关产品推荐
相关产品推荐

