Parsing 为什么这个Haskell';如果';陈述

Parsing 为什么这个Haskell';如果';陈述,parsing,haskell,sudoku,Parsing,Haskell,Sudoku,我正在寻找一个提示或解释,说明为什么这段代码在块中的第一条elseif语句上不断出现解析错误。它说缩进或括号可能有问题,但我似乎找不到。所以我在寻找另一双有经验的眼睛,让我走上正确的道路。我觉得我忽略了一些很小的东西,但我就是找不到。这是一个数独解算器(我承认整个数独解算器是一个课堂作业。这是我第一次发帖,所以我不能100%确定这是一个可以接受的问题,如果不是,请让我知道) 此函数用于获取一个数独游戏板(基本上是列表列表)和两个整数,这两个整数是您正在查看的板的3x3部分的坐标,然后从该3x3部

我正在寻找一个提示或解释,说明为什么这段代码在块中的第一条elseif语句上不断出现解析错误。它说缩进或括号可能有问题,但我似乎找不到。所以我在寻找另一双有经验的眼睛,让我走上正确的道路。我觉得我忽略了一些很小的东西,但我就是找不到。这是一个数独解算器(我承认整个数独解算器是一个课堂作业。这是我第一次发帖,所以我不能100%确定这是一个可以接受的问题,如果不是,请让我知道)

此函数用于获取一个数独游戏板(基本上是列表列表)和两个整数,这两个整数是您正在查看的板的3x3部分的坐标,然后从该3x3部分返回数字序列

我知道这不是解决这个问题的哈斯凯尔方法(我最后有点野蛮地强迫了它),我真的只学习了哈斯凯尔几个星期,但我想弄清楚为什么else if总是作为一个错误出现

getBox :: Board -> Int -> Int -> Sequence
getBox b x y = do
  let i = x
  let j = y


  let x0 = b!!0
  let x1 = b!!1
  let x2 = b!!2
  let x3 = b!!3
  let x4 = b!!4
  let x5 = b!!5
  let x6 = b!!6
  let x7 = b!!7
  let x8 = b!!8

  if (i==0 && j==0)
      then let z = [x0!!0, x0!1, x0!!2, x1!!0 x1!!1, x1!!2, x2!!0, x2!!1, x2!!2]
  else if (i==0 && j==1)
      then let z = [x0!!3, x0!4, x0!!5, x1!!3 x1!!4, x1!!5, x2!!3, x2!!4, x2!!5]
  else if (i==0 && j==2)
      then let z = [x0!!6, x0!7, x0!!8, x1!!6 x1!!7, x1!!8, x2!!6, x2!!7, x2!!8]
  else if (i==1 && j==0)
      then let z = [x3!!0, x3!!1, x3!!2, x4!!0, x4!!1, x4!!2, x5!!0, x5!!1, x5!!2]
  else if (i==1 && j==1)
      then let z = [x3!!3, x3!!4, x3!!5, x4!!3, x4!!4, x4!!5, x5!!3, x5!!4, x5!!5]
  else if (i==1 && j==2)
      then let z = [x3!!6, x3!!7, x3!!8, x4!!6, x4!!7, x4!!8, x5!!6, x5!!7, x5!!8]
  else if (i==2 && j==0)
      then let z = [x6!!0, x6!!1, x6!!2, x7!!0, x7!!1, x7!!2, x8!!0, x8!!1, x8!!2]
  else if (i==2 && j==1)
      then let z = [x6!!3, x6!!4, x6!!5, x7!!3, x7!!4, x7!!5, x8!!3, x8!!4, x8!!5]
  else let z = [x6!!6, x6!!7, x6!!8, x7!!6, x7!!7, x7!!8, x8!!6, x8!!7, x8!!8]

只要删除
let z=
,它就会出现在任何地方,你就会发现下一个错误。

一个
let
表达式有一个绑定和一个主体。一个典型的
let
表达式是:

let x = 2 in x + x
    ^^^^^    ^^^^^
   binding    body
这只意味着用身体中的
x
替换
2
。这就是
let
的全部含义(也就是说,您可以通过替换来手动摆脱
let
)。它被
do
块中允许的
let
语法所掩盖,这可能会给人一种印象,它就像命令式语言中的可变变量,但事实并非如此

do 
    let i = x
    let j = y
    pure (i + j)
意味着

也就是说,let的主体是
do
块的其余部分

任何变量都可以追溯到一个唯一的定义或函数参数。一个变量不能由多个不同的
let
语句动态地定义,正如您正在尝试的那样。只需定义一次
z
。在您的情况下,这可以通过保护来完成,这是一种生成条件定义的方法

let z
    | i == 0 && j == 0 = [x0!!0, x0!!1, -- oh my god I am not typing this
    | i == 0 && j == 1 = [x0!!3, x0!!4, -- more?
    | ...
您也可以在没有防护装置的情况下完成此操作,您只需移动
链(如果
内):

let z = if i == 0 && j == 0 then [...]
        else if i == 0 && j == 1 then [...]
        ...

我希望这有帮助。希望你的暴力解决方案的痛苦可以平摊。

这是解决这个问题的一个可怕的方法。您应该尝试学习haskell的基本语法方法,而不是强行这样做。
let
后面必须有一些使用定义变量的代码,否则它完全没有用。所有的
let
s后面都没有任何内容。@FyodorSoikin好吧,前11个是“好”的,因为它们位于do块中(尽管显然非常混乱)。天哪,这段代码中有很多奇怪之处。我可以建议您在完成您想要的任务后,将其交给您吗?请不要使用
do
,除非您理解其中的含义。这通常会导致人们试图用Haskell的命令式写作风格。
let z = if i == 0 && j == 0 then [...]
        else if i == 0 && j == 1 then [...]
        ...