Haskell 使用';让';在';如果';表达

Haskell 使用';让';在';如果';表达,haskell,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 = r

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

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
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
如何检查多个表达式并在列表中添加新元素?
我不仅搜索命令式解决方案,还搜索功能性解决方案。

编辑:感谢sepp2k指出了我的意图。这比我戴着哈斯凯尔彩色眼镜摸索更迫切

下面是一个快速解决方案:

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 [])
result=(如果x>0,则[3]否则[])++
(如果y>0,则[5]否则[])++
(如果x

(旧答案已删除。)

编辑:感谢sepp2k指出了我的意图。这比我戴着哈斯凯尔彩色眼镜摸索更迫切

下面是一个快速解决方案:

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 [])
result=(如果x>0,则[3]否则[])++
(如果y>0,则[5]否则[])++
(如果x
(删除旧答案。)

三件事:

  • 您可以在
    if
    表达式中使用
    let
    ,但在
    中或在
    do
    块中,它需要后跟
    。无论哪种方式,使用您刚刚绑定的名称的表达式都需要在相同的
    中,如果
    。也就是说,你可以做:

    if x > 0
    then let a = 42 in a+x
    else 23      
    
    但不是

    if x > 0
    then let a = 42 in ()
    else let a = 23 in ()        
    print a
    
  • 不能使用
    let
    更改现有变量的值。事实上,你永远不能改变一个变量的值

  • 如果在
    =
    的右侧使用
    =
    的左侧绑定的名称,它将递归地引用自身,而不是以前的任何绑定。换句话说,
    让x=x+1
    引起无限递归,它不会将
    x
    的值增加1

  • 要想做您想做的事情,您需要将代码重组为如下内容:

    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
    
    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
    
    让result1=如果x>0,那么[3]else[]
    让result2=如果y>0,则result1++[5]否则result1
    设result3=如果x
    请注意,从性能角度来看,在末尾使用
    ++
    进行追加通常不是一个好主意,而不是使用
    ,然后在末尾使用
    反转

    三件事:

  • 您可以在
    if
    表达式中使用
    let
    ,但在
    中或在
    do
    块中,它需要后跟
    。无论哪种方式,使用您刚刚绑定的名称的表达式都需要在相同的
    中,如果
    。也就是说,你可以做:

    if x > 0
    then let a = 42 in a+x
    else 23      
    
    但不是

    if x > 0
    then let a = 42 in ()
    else let a = 23 in ()        
    print a
    
  • 不能使用
    let
    更改现有变量的值。事实上,你永远不能改变一个变量的值

  • 如果在
    =
    的右侧使用
    =
    的左侧绑定的名称,它将递归地引用自身,而不是以前的任何绑定。换句话说,
    让x=x+1
    引起无限递归,它不会将
    x
    的值增加1

  • 要想做您想做的事情,您需要将代码重组为如下内容:

    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
    
    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
    
    让result1=如果x>0,那么[3]else[]
    让result2=如果y>0,则result1++[5]否则result1
    设result3=如果x

    请注意,从性能角度来看,在末尾使用
    ++
    进行追加通常不是一个好主意,而不是使用
    ,然后在末尾使用
    反转列表。

    如果使用
    的话,您认为
    的方式也有问题。在Haskell
    中,如果
    是一个表达式,即它的计算结果为一个值。因此,它必须始终伴有
    else
    分支。马塞洛的例子应该澄清这一点。如果您想要命令式语言中的
    If
    语句,那么您就需要
    Control.Monad.when
    Control.Monad。在Haskell
    中,如果
    是一个表达式,即它的计算结果为一个值。因此,它必须始终伴有
    else
    分支。马塞洛的例子应该澄清这一点。如果您希望在命令式语言中使用类似于
    If
    语句的语句,那么您就有了
    Control.Monad.when
    Control.Monad。不幸的是,除非

    您的代码有很多地方出错。第一个问题是顶行的
    do
    :您没有使用任何monad,因此您根本不应该使用它。代码的其余部分试图以命令式的方式工作,但这(毫不奇怪)在Haskell中不起作用。在Haskell中,每个表达式都需要有一个结果;因此,所有if语句的格式必须为<代码>if。。。然后。。。否则…
    。同样,每个let绑定的形式必须是
    let。。。在…
    ;无法更改变量的值,因此如果您在
    中取消了
    ,则不会发生任何事情。正因为如此,如果可以执行,每一行都会尝试创建一个列表,该列表由所有元素组成,最后有一个三,换句话说,一个自引用列表!(这种事情的典型例子是
    let one=1:ones in one
    ,创建一个尾部为自身的列表,因此只包含
    1
    s。)

    现在的问题是,你的函数想做什么?您有四个布尔条件,并且希望为每个条件向列表中添加不同的元素。你可以用很多方法来写这个。一种方法是

    foo :: Integer -> Integer -> Integer
    foo a b = let Coord x y = boo a b
                  checkAdd cond elem = if cond then (elem :) else id
              in foldr (uncurry checkAdd) []
                       [(x > 0, 3), (y > 0, 5), (x > a, 7), (y > b, 9)]
    
    首先,我们调用
    boo
    并查看结果。然后我们定义一个
    checkAdd
    函数,其类型为
    checkAdd::Bool->a->([a]->[a])