是否可以在Haskell中执行嵌套的if语句?

Dav*_*ett 2 haskell if-statement

我正在尝试对列表中的3个元素进行排序.但是我在将其翻译成haskell时遇到了麻烦.是否有可能在haskell中执行嵌套if语句?我一直在尝试模式匹配,但它永远带我.

if (x < y) {
    if (z < x) swap(x,z);
} else {
   if (y < z) swap(x,y);
else swap(x,z);
} 
  if(z<y) swap(y,z);
Run Code Online (Sandbox Code Playgroud)

这是我试过的

intCMP :: Int -> Int -> Ordering
intCMP a b | a == b =EQ
           | a < b = LT
           | otherwise = GT

sort3 :: Ord a => (a -> a -> Ordering) -> [a] -> [a]
sort3 cmp [a,b,c] = if cmp a b == LT then
                   if cmp a c == Lt then
                      if cmp b c == LT then
                         [a,b,c]
                      else
                         [a,c,b]
                   else
                      [c,a,b]
                else if cmp b c == LT then
                        if cmp a c == LT then
                             [b,a,c]
                        else
                             [b,c,a]
                else
                     [c,b,a]
Run Code Online (Sandbox Code Playgroud)

lis*_*rus 8

这个技巧是在Haskell if中不是一个声明,而是一个表达式.它从一个分支返回一个值,而不是在那里执行代码.事实上,if虽然可能只是一个函数的语法糖if :: Bool -> a -> a -> a (当然,没有这样的函数可以存在,因为if是一个关键字;但是,如果命名方式不同,就像这样,可以简单地实现这样的函数).

所以,是的,嵌套if语句是可能的,就像任何表达式一样

max x y z = if x < y then (if y < z then z else y) else (if x < z then z else x)
Run Code Online (Sandbox Code Playgroud)

但是,这并不直接适用于您的情况,因为您不能swap这么简单:所有值在Haskell中都是不可变的.所以,如果你不想使用monad或类似的东西,解决方案可能是返回排序列表:

sort [x,y,z] =
    if x < y then
        (if y < z then
            [x,y,z]
        else
            (if x < z then
                [x,z,y]
                    else
                [z,x,y]
            )
        )
    else
        undefined -- implement other cases here
Run Code Online (Sandbox Code Playgroud)


lef*_*out 7

正如lisyarus所说,你可以做到这一点.但是,if在Haskell中通常有点尴尬; 通常,模式匹配是一个更好的选择 - 这可以避免布尔瓶颈,并允许您直接解构有意义的值.在你的情况下,最明显的事情是== LTcase表达式替换丑陋的检查:

sort3 cmp [a,b,c] = case cmp a b of
      LT -> case cmp a c of
         LT -> ...
Run Code Online (Sandbox Code Playgroud)

既然你总是检查所有这三个,那么就没有必要嵌套检查; 你不妨一次检查一下:

sort3 cmp [a,b,c] = case (cmp a b, cmp a c, cmp b c) of
       (GT, _ , GT) -> [c,b,a]
       (GT, LT, _ ) -> [b,a,c]
       (_ , LT, GT) -> [a,c,b]
       (_ , GT, _ ) -> [c,a,b]
       (GT, _ , _ ) -> [b,c,a]
       _            -> [a,b,c]
Run Code Online (Sandbox Code Playgroud)