在haskell中执行列表推导时得到解析错误

时间:2014-11-03 03:52:26

标签: haskell

我正在编写一个这样的函数:

testing :: [Int] -> [Int] -> [Int]
testing lst1 lst2 =
      let t = [ r | (x,y) <- zip lst1 lst2, let r = if y == 0 && x == 2 then 2 else y ]
      let t1 = [ w | (u,v) <- zip t (tail t), let w = if (u == 2) && (v == 0) then 2 else v]
      head t : t1

第一个让我们做的是:返回一个这样的列表:[2,0,0,0,1,0],从第二个let和下一行,我希望输出如下:[2 ,2,2,2,1,0]。但是,它没有工作,并提供解析错误!!

我做错了什么?

2 个答案:

答案 0 :(得分:3)

有两种let:“let / in”类型,可以出现在表达式可以的任何位置,“let没有{ {1}}“善良,必须出现在理解或阻止中。由于您的函数定义不在其中,因此in必须使用let,例如:

in

或者,由于您可以在每个testing :: [Int] -> [Int] -> [Int] testing lst1 lst2 = let t = [ r | (x,y) <- zip lst1 lst2, let r = if y == 0 && x == 2 then 2 else y ] in let t1 = [ w | (u,v) <- zip t (tail t), let w = if (x == 2) && (y == 0) then 2 else y] in return (head t : t1) 中定义多个内容,因此您可以考虑:

let

代码还有其他问题,但这应该会让你达到解析的程度,至少。

答案 1 :(得分:0)

通过let-binding形成表达式,通常需要

let bindings 
in 
  expressions

(涉及monad时有例外)。

因此,您的代码可以按如下方式重写(简化rw,这些并非真正必要):

testing :: [Int] -> [Int] -> [Int]
testing lst1 lst2 =
      let t = [ if y == 0 && x == 2 then 2 else y | (x,y) <- zip lst1 lst2]
          t1 = [ if (v == 0) && (u == 2) then 2 else v | (u,v) <- zip t (tail t)]
      in
        head t : t1

(注意,我还切换了uv,以便t1和t具有相似的形式。

现在给出了[2,0,0,0,1,0]之类的列表,您的代码似乎正在尝试替换0 with 2 if the previous element is 2(来自您的代码模式),因此最终所需的输出为[2,2,2,2,1,0]

要实现这一点,仅使用两个列表推导或任何固定数量的理解是不够的。您需要以某种方式递归地应用此过程(一次又一次)。因此,我们可以写出一个步骤(并重复应用),而不是仅仅执行两个步骤。使用t1 = ...行,一步功能可以是:

testing' lst = 
    let               
        t1 = [ if (u == 2) && (v == 0) then 2 else v | (u,v) <- zip lst (tail lst)]
    in
      head lst : t1

现在这给出了:

*Main> testing'  [2,0,0,0,1,0]
[2,2,0,0,1,0]

,正如所料。

剩下的工作是根据需要多次应用testing'。在这里应用它(length lst)次就足够了。因此,我们可以先写一个辅助函数,在参数上应用另一个函数n次,如下所示:

apply_n 0 f x = x
apply_n n f x = f $ apply_n (n - 1) f x

这可以满足您的期望:

*Main> apply_n (length [2,0,0,0,1,0]) testing' [2,0,0,0,1,0]
[2,2,2,2,1,0]

当然,您可以将上述内容包含在以下函数中:

testing'' lst = apply_n (length lst) testing' lst

最后:

*Main> testing''  [2,0,0,0,1,0]
[2,2,2,2,1,0]

注意:这不是填充的唯一方法,请参阅fill2函数in my answer to another question以获取使用有限状态机实现相同功能的示例。