Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Group matches in case expression

Tags:

haskell

I have a variable like

a = 3

For some values of a, I have the same function I want to call:

case a of
     3 -> print "hello"
     4 -> print "hello"
     5 -> print "hello"
     6 -> print "hello something else"

So for a=3, a=4 and a=5 I make the same function call. Can I group these better? I'm kinda looking for a solution which would be:

case a of
     3 || 4 || 5 -> print "hello"
     6           -> print "hello something else"

This doesn't work of course, but hopefully you get where I want to end up with.

Thanks.

like image 711
Niklas9 Avatar asked Mar 02 '13 10:03

Niklas9


People also ask

Can we write GROUP BY in case statement?

The case statement in SQL returns a value on a specified condition. We can use a Case statement in select queries along with Where, Order By, and Group By clause. It can be used in the Insert statement as well.

How do you use GROUP BY expression?

The GROUP BY statement groups rows that have the same values into summary rows, like "find the number of customers in each country". The GROUP BY statement is often used with aggregate functions ( COUNT() , MAX() , MIN() , SUM() , AVG() ) to group the result-set by one or more columns.

Can we use aggregate function in case statement?

CASE statement in SQL and aggregate functions Aggregate functions in SQL Server perform calculations and return a single value. Examples of aggregate functions are MIN, MAX, COUNT, ABG and CHECKSUM. For this purpose, we use the COUNT aggregate function in SQL Server.

How do I apply GROUP BY condition?

Syntax: SELECT column1, function_name(column2) FROM table_name WHERE condition GROUP BY column1, column2 HAVING condition ORDER BY column1, column2; function_name: Name of the function used for example, SUM() , AVG(). table_name: Name of the table. condition: Condition used.


2 Answers

How about

case a of
     _ | a == 3 || a == 4 || a == 5
       -> print "hello"
     6 -> print "hello something else"

Less tedious to write would be

case a of
     _ | a `elem` [3, 4, 5]
       -> print "hello"
     6 -> print "hello something else"

or

case a of
     _ | 3 <= a && a <= 5
       -> print "hello"
     6 -> print "hello something else"

or even, if in your real program there were a lot of possible values for you to match against, something like this:

import qualified Data.Set as S

valuesToMatchAgainst :: S.Set Int
valuesToMatchAgainst = S.fromList [3, 4, 5]

-- ...

    case a of
         _ | a `S.elem` valuesToMatchAgainst
           -> print "hello"
         6 -> print "hello something else"

(I'm presuming you understand already that _ is a wildcard that matches any value, and that | introduces a guard.)

like image 64
dave4420 Avatar answered Oct 10 '22 02:10

dave4420


You can do different things to improve your code. First, if all branches call the same function then why not:

print (case a of 
         3 -> "hello"
         4 -> "hello"
         5 -> "hello"
         6 -> "hello something else")

This factors out more of the common behaviour of your code. Second, you seem to ask about grouping the 3,4 and 5 cases together, the best way might be to factor out a categorization function:

 let cat 3 = True
     cat 4 = True
     cat 5 = True
     cat 6 = False
 in print (case cat a of True -> "hello"
                         False -> "hello something else")

You can combine this with one of the alternatives suggested by the previous poster (cat x = xelem[3,4,5] etc).

like image 34
Dominique Devriese Avatar answered Oct 10 '22 03:10

Dominique Devriese