2017-10-16 108 views
2

我想排序列表中的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); 

这是我曾尝试

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] 
+1

“是”此外,那些嵌套的if语句可以变平。 – user2864740

+0

你是什么意思扁平? –

+4

Haskell并不真的有if语句。它有如果表达式。什么让你怀疑他们的巢穴能力? –

回答

8

这招是在Haskell if不是一个声明,但表达它returnes从树枝的一个值,而不是执行的代码那里。事实上,if可虽然是只是一个函数的句法糖if :: Bool -> a -> a -> a(当然,不存在这样的功能,因为if是关键字;仍然可以简单地实现这样的功能,如果命名不同,like this

所以,是的,嵌套if语句是可能的,就像任何表情,像在

​​

然而,这并不直接适用于你的情况,因为你不能做swap那么容易:所有值都在Haskell中不可变。所以,如果你不想使用单子或类似的东西,一个解决方案可能是返回排序列表:

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 
+1

我不明白你想说的是如何为'if'函数构造语法糖。当然没有这样的功能,因为'if'是一个保留的令牌。您可能会说它是'Data.Bool.bool :: a - > a - > Bool - > a'的语法替代,尽管当然这些参数的顺序不同。 – amalloy

+0

@amalloy谢谢,我会改变措辞。如果这听起来令人困惑,我很抱歉。我的意思是'if'不是神奇的东西,*可以被认为是一个函数if :: Bool - > a - > a - > a'。当然,没有,也不可能是这样的功能,你是对的。尽管如此,人们可以用不同的名称命名,在函数中有效实现'if'运算符。 – lisyarus

+0

对,并且该函数已经存在并被称为bool。 – amalloy

7

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

sort3 cmp [a,b,c] = case cmp a b of 
     LT -> case cmp a c of 
     LT -> ... 

既然你总是检查所有三个反正不过,真的有没有必要窝的检查;你不妨检查他们都曾:

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] 
0

对于三个要素,也不要紧,但一旦你到四,它确实有助于有交换的概念,但我不会去你的交换机制。你可以通过给每个计算阶段自己的函数来做到这一点。

data Triple a = Triple a a a 
sort3, sort3', sort3'' 
    :: Ord a => Triple a -> Triple a 

sort3 [email protected](Triple x y z) 
    | x <= y = sort3' t 
    | otherwise = sort3' (Triple y x z) 

-- Precondition : the first two elements are in order 
sort3' [email protected](Triple x y z) 
    | x <= z = sort3'' t 
    | otherwise = Triple z x y 

-- Precondition: The smallest element is first 
sort3'' [email protected](Triple x y z) 
    | y <= z = t 
    | otherwise = Triple x z y