在'if'表达式中使用'let'

dem*_*mas 1 haskell

我需要一个像这样工作的函数:

foo :: Integer -> Integer -> [Integer]
foo a b = do
           let result = []
           let Coord x y = boo a b
           if x > 0
              let result = result ++ [3]
           if y > 0 
              let result = result ++ [5]
           if x < a
              let result = result ++ [7]
           if y < b
              let result = result ++ [9]
           result
Run Code Online (Sandbox Code Playgroud)

我不能使用防护因为结果可以有多个元素.但正如我所见,我不能在'if'表达式中使用'let':

all_possible_combinations.hs:41:14: parse error on input `let'
Run Code Online (Sandbox Code Playgroud)

如何检查多个表达式并在列表中添加新元素?我不仅搜索命令式解决方案,还搜索功能性解决方案.

dav*_*420 10

其他人说你为什么尝试不起作用.这是一个简洁的方式来做你想要的:

foo :: Integer -> Integer -> [Integer]
foo a b = map snd (filter fst [(x > 0, 3),
                               (y > 0, 5),
                               (x < a, 7),
                               (y < a, 9)])
  where Coord x y = boo a b
Run Code Online (Sandbox Code Playgroud)

那么这是如何工作的呢?

我们从对列表开始.每对中的第二个元素是我们可能希望包含在返回值中的值foo.每对中的第一个元素告诉我们是否真的想要包含它.

然后我们调用filter fst,抛出条件为假的所有对.

最后,我们调用map snd,抛弃条件(所有剩下的条件都是真的),并保留我们感兴趣的值.


Mar*_*tos 5

编辑:我感谢sepp2k指出了意图.这比我能用我的Haskell色眼镜更让人感到紧迫......

这是一个快速肮脏的解决方案:

result = (if x > 0 then [3] else []) ++
         (if y > 0 then [5] else []) ++
         (if x < a then [7] else []) ++
         (if y < b then [9] else [])
Run Code Online (Sandbox Code Playgroud)

(旧答案已删除.)

  • 实际上这对他的代码不起作用.如果所有四个条件都成立,他希望结果包含`[3,5,7,9]`.请注意,条件并不相互排斥. (2认同)

sep*_*p2k 5

三件事:

  1. 可以letif表达式中使用,但需要indo块之后或之内.无论哪种方式,使用您刚刚绑定的名称的表达式都let需要相同if.即你可以这样做:

    if x > 0
    then let a = 42 in a+x
    else 23      
    
    Run Code Online (Sandbox Code Playgroud)

    但不是

    if x > 0
    then let a = 42 in ()
    else let a = 23 in ()        
    print a
    
    Run Code Online (Sandbox Code Playgroud)
  2. 您无法使用let更改现有变量的值.事实上,你永远无法改变变量的值.

  3. 如果你=在RHS 上使用绑定在RHS上的名称=,它将递归地引用自身 - 而不是任何先前的绑定.换句话说let x = x+1,导致无限递归,它不会增加一个值x.

要做你想做的事,你需要将你的代码重组为这样的东西:

let result1 = if x > 0 then [3] else []
let result2 = if y > 0 then result1 ++ [5] else result1
let result3 = if x < a then result2 ++ [7] else result2
if y < b then result3 ++ [9] else result3
Run Code Online (Sandbox Code Playgroud)

请注意,使用++最后附加,而不是在最后使用:然后reverse输入列表通常是一个坏主意,性能明智.