我需要一个像这样工作的函数:
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,抛弃条件(所有剩下的条件都是真的),并保留我们感兴趣的值.
编辑:我感谢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)
(旧答案已删除.)
三件事:
您可以let在if表达式中使用,但需要in在do块之后或之内.无论哪种方式,使用您刚刚绑定的名称的表达式都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)您无法使用let更改现有变量的值.事实上,你永远无法改变变量的值.
如果你=在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输入列表通常是一个坏主意,性能明智.