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)
这个技巧是在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)
正如lisyarus所说,你可以做到这一点.但是,if在Haskell中通常有点尴尬; 通常,模式匹配是一个更好的选择 - 这可以避免布尔瓶颈,并允许您直接解构有意义的值.在你的情况下,最明显的事情是== LT用case表达式替换丑陋的检查:
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)
| 归档时间: |
|
| 查看次数: |
704 次 |
| 最近记录: |