我正在尝试对列表中的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]
答案 0 :(得分:8)
这个技巧是在Haskell中if
不是一个语句,而是一个表达式。它从其中一个分支返回一个值,而不是在那里执行代码。实际上,if
可能只是函数if :: Bool -> a -> a -> a
的语法糖(当然,不存在这样的函数,因为if
是一个关键字;仍然,一个人可以轻而易举地实现这样一个函数,如果命名不同,like this)。
所以,是的,嵌套的if
语句是可能的,就像任何表达式一样,如
max x y z = if x < y then (if y < z then z else y) else (if x < z then z else x)
但是,这并不直接适用于您的情况,因为您无法轻松地执行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
答案 1 :(得分:7)
正如lisyarus所说,你可以做到这一点。但是,if
在Haskell中通常有点尴尬;通常,模式匹配是一个更好的选择 - 这可以避免布尔瓶颈,并允许您直接解构有意义的值。在您的情况下,最明显的事情是用== LT
表达式替换丑陋的case
检查:
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]
答案 2 :(得分:0)
对于三个元素,它并不重要,但是一旦你达到四个,那么交换的概念确实很有帮助,尽管我不会选择你的交换机制。你可以通过给每个计算阶段赋予它自己的功能来做到这一点。
>>> session = requests.Session()
>>> response = session.request('GET', 'http://httpbin.org/cookies/set?foo=bar')
>>> session.cookies # no policy, so cookie got set
<RequestsCookieJar[Cookie(version=0, name='foo', value='bar', port=None, port_specified=False, domain='httpbin.org', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={}, rfc2109=False)]>
>>> session.cookies.clear() # clean slate, no cookies
>>> session.cookies
<RequestsCookieJar[]>
>>> session.cookies.set_policy(BlockAll())
>>> response = session.request('GET', 'http://httpbin.org/cookies/set?foo=bar')
>>> session.cookies # with policy, cookies still empty
<RequestsCookieJar[]>