在where子句中定义以下功能时,为什么不在范围内?

时间:2018-09-26 01:44:58

标签: haskell

import               Data.Char (chr, ord)

num2Str :: Int -> String
num2Str n | n < 26 = [num2Chr n]
num2Str n          = num2Chr n : num2Str (n - 26)
  where {
    num2Chr :: Int -> Char;
    num2Chr n = chr(97 + n `mod` 26)
  }

这会导致错误

    * Variable not in scope: num2Chr :: Int -> Char
    * Perhaps you meant `num2Str' (line 132)
    |
132 | num2Str n | n < 26 = [num2Chr n]
    |                       ^^^^^^^

我尝试了几种替代布局的方法,但是似乎都没有用。

次要更新

代码中存在与问题无关的逻辑错误;这是更正的版本:

import               Data.Char (chr, ord)
num2LcStr :: Int -> String
num2LcStr n | n < 26    = [num2Chr n] 
            | otherwise = 'z' : num2LcStr (n - 26)
  where
    num2Chr nn = chr(97 + nn `mod` 26)

1 个答案:

答案 0 :(得分:5)

num2Char函数不在第一个定义num2Str n | n < 26的范围内,因为where子句仅“作用于”第二个定义num2Str n。解决问题的最简单方法是通过仅分隔功能来修改功能,如下所示:

import Data.Char (chr, ord)

num2Str :: Int -> String
num2Str n | n < 26 = [(num2Chr n)]
num2Str n          = num2Chr n : num2Str (n - 26)

num2Chr :: Int -> Char
num2Chr n = chr(97 + n `mod` 26)

但是,出于风格的考虑,最好是充分利用后卫:

num2Str :: Int -> String
num2Str n | n < 26    = [(num2Chr n)]
          | otherwise = num2Chr n : num2Str (n - 26)
  where
    num2Chr :: Int -> Char
    num2Chr n = chr(97 + n `mod` 26)

我建议您使用以上样式,以确保完整性,简洁性和正确性。

关于语法的注释:不要在where子句周围使用方括号,也不需要分号。

如果您真的想使代码保持相似并说明我对where子句的意思:

num2Str :: Int -> String
num2Str n | n < 26 = [(num2Chr n)]
  where 
    num2Chr n = chr(97 + n `mod` 26)
num2Str n          = num2Chr n : num2Str (n - 26)
  where 
    num2Chr n = chr(97 + n `mod` 26)

这是有效的,但是样式很差。每个where的作用域是其上方的功能。有关更多信息和参考,请参见:http://learnyouahaskell.com/syntax-in-functions#where