2017-10-16 59 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