Haskell中let..in结构内where子句作用域问题及改写方法
Haskell let-in结构where子句作用域错误修复
问题复现
运行以下代码时会抛出Variable not in scope: s错误:
encode :: String -> String encode xs = let s = normalize xs in case s of [] -> [] _ -> encode' s row col where row = isqrt (length s) col = length s `div` row
错误原因
Haskell的作用域规则规定:where子句的绑定仅对其直接附属的语法结构生效,无法访问同层级let块内定义的变量。上述代码中where块内计算row和col时引用的s属于外层let的绑定变量,不在where的可访问范围内,因此触发未定义变量错误。
正确改写方案
有两种符合Haskell语法规范的改写方式:
方案1:将所有局部变量统一放到let块内定义
去掉原有的where子句,把row、col的绑定和s一起放在let块中,保证所有变量处于同一作用域:
encode :: String -> String encode xs = let s = normalize xs row = isqrt (length s) col = length s `div` row in case s of [] -> [] _ -> encode' s row col
方案2:将所有局部变量统一放到where块内定义
把s的绑定也迁移到where块中,让所有局部绑定都由where统一管理,这也是Haskell中更常用的局部变量定义风格:
encode :: String -> String encode xs = case s of [] -> [] _ -> encode' s row col where s = normalize xs row = isqrt (length s) col = length s `div` row
内容的提问来源于stack exchange,提问作者Abhijit Sarkar
相关产品推荐
相关产品推荐

