F# bit flags enum - f#

I would like to create a bitflags enum in F#, using bitshift operators for readability: e.g.
[<Flags>]
type DaysOfWeek =
| Monday = 1 <<< 0
| Tuesday = 1 <<< 1
| Wednesday = 1 <<< 2
| Thursday = 1 <<< 3
| Friday = 1 <<< 4
| Saturday = 1 <<< 5
| Sunday = 1 <<< 6
However, the F# compiler dislikes this. It says "unexpected infix operator in member definition".
I would prefer this approach over manual powers of two. Is there a way to convince the compiler that I'm not being evil?

It's not exactly what you asked for, but you can write the binary longhand using the 0b prefix, eg:
[<Flags>]
type DaysOfWeek =
| Monday = 0b0000001
| Tuesday = 0b0000010
| Wednesday = 0b0000100
| Thursday = 0b0001000
| Friday = 0b0010000
| Saturday = 0b0100000
| Sunday = 0b1000000

Alternative way that separates the cases from the values, more verbose but more flexible:
type DaysOfWeek =
| Monday
| Tuesday
| Wednesday
| Thursday
| Friday
| Saturday
| Sunday
with
static member Flag x =
let bit n = 1 <<< n
match x with
| Monday -> bit 0
| Tuesday -> bit 1
| Wednesday -> bit 2
| Thursday -> bit 3
| Friday -> bit 4
| Saturday -> bit 5
| Sunday -> bit 6

This is the approach recommended by Dave Fancher in The Book of F#
Use the Flags attribute with values that are powers of two:
open System
[<Flags>]
type DayOfWeek =
| None = 0
| Sunday = 1
| Monday = 2
| Tuesday = 4
| Wednesday = 8
| Thursday = 16
| Friday = 32
| Saturday = 64
The Flags attribute isn't required, but makes your intention clear.
You can now represent combinations of values using the bitwise operators:
let weekend = DayOfWeek.Saturday ||| DayOfWeek.Sunday

Related

How to get all values (of particular column) of a lookup value in a single cell?

I have headers (dptype, day, batchtimings).how to get multiple (day and batch-timings values) of an individual lookup value in a single cell of another sheet?
Example:
Dp type | day |batchtimings
---------|-------------|----------------
a | Saturday | 10-11
b | friday | 11-12
a | monday | 01-02
y | tuesday | 02-03
b | sunday | 04-05
a | wednesday | 04-07
c | sunday | 03-04
a | friday | 10-12
v | monday | 10-11
b | thursday | 11-12
y | monday | 09-10
I want individual dptype's all the day and batch timings values in a single cell (unique)
I want-example:
dp type batches
------------------------------
| Saturday:10-11
a | monday :1-2
| wednesday:4-7
| friday:10-12
--------|--------------------
b | friday:11-12
| Sunday:4-5
| thursday:11-12
--------|--------------------
y | tuesday:2-3
| monday:9-10
Get your list of Unique Types:
=UNIQUE(A2:A12)
Then reference those with:
=join(char(10),UNIQUE(FILTER(B:B&":"&text(C:C,"mm-dd"),A:A=F1)))
You can try
=IFNA( JOIN (" :"), FILTER(B1:C10, A1:A10="A"))
Where you would replace the value at the end with what your looking for
use:
=ARRAYFORMULA({SORT(UNIQUE(FILTER(A2:A, A2:A<>""))), TRANSPOSE(SUBSTITUTE(TRIM(
QUERY(QUERY(QUERY(UNIQUE({A2:C, B2:B&":"&TO_TEXT(C2:C)}),
"select max(Col4) where Col1 is not null group by Col2 pivot Col1"),
"offset 1", 0),,999^99)), " ", CHAR(10)))})

Maximum of column 1 where value of column 2 matches some condition

Let's say I have the following in a table :
A | B | desired_output
----------------------------
1 | 10 | 1 | 0
2 | 20 | 7 | 0
3 | 30 | 3 | 0
4 | 20 | 2 | 0
5 | 30 | 5 | 1
I'd like to find a formula for each of the cells in the desired_output column which looks at the max of B1:B5 but only for rows for which A = max(A1:A5)
If that's not clear, I'll try to put it another way :
for all the rows in A1:A5 that are equal to max(A1:A5) // so that's rows 3 and 5
find the one which has the max value on B // so between B3 and B5, that's B5
output 1 for this one, 0 for the other
I'd say there would be a where somewhere if such a function existed, something like = if(B=(max(B1:B5) where A = max(A1:A5)), 1, 0) but I can't find how to do it...
I can do it in two columns with a trick :
A | B | C | D
----------------------------
1 | 10 | 1 | | 0
2 | 20 | 7 | | 0
3 | 30 | 3 | 3 | 0
4 | 20 | 2 | | 0
5 | 30 | 5 | 5 | 1
With Cn = if(An=max(A$1:A$5),Bn,"") and Dn = if(Cn = max(C$1:C$5), 1, 0)
But I still can't find how to do it in one column
For systems without MAXIFS, put this in C1 and fill down.
=--(B1=MAX(INDEX(B$1:B$5-(A$1:A$5<>MAX(A$1:A$5))*1E+99, , )))
=ARRAYFORMULA(IF(LEN(A1:A), IF(IFERROR(VLOOKUP(CONCAT(A1:A&"×", B1:B),
JOIN("×", QUERY(A1:B, "order by A desc, B desc limit 1")), 1, 0), )<>"", 1, 0), ))
or shorter:
=ARRAYFORMULA(IF(A:A<>"",N(A:A&"×"&B:B=JOIN("×",SORTN(A:B,1,,1,0,2,0))),))
=ARRAYFORMULA(IF(A:A<>"",N(A:A&B:B=JOIN(,SORTN(A:B,1,,1,0,2,0))),))
How about the following:
=--AND(A5=MAX($A$1:$A$5),B5=MAXIFS($B$1:$B$5,$A$1:$A$5,MAX($A$1:$A$5)))

googlesheet - Call month API in query statement not work as expected

To summarize each month's balance, I try to call month API in query statement. but sounds like the month API always return (month - 1) but not month.
Example data:
| Type | TransDate | Amount |
|---------+------------+---------|
| Sale | 08/13/2017 | -40.97 |
| Return | 08/10/2017 | 127.48 |
| Payment | 08/07/2017 | 2194.45 |
| Sale | 08/07/2017 | -100.97 |
| Sale | 08/06/2017 | -143.44 |
| Sale | 07/02/2017 | -143.44 |
| Sale | 07/03/2017 | -7.55 |
| Sale | 08/04/2017 | -8.03 |
I use below formula:
=query(A:C,"select MONTH(B),sum(C) where A = 'Sale' or A = 'Return' group by MONTH(B) label MONTH(B) 'Month',sum(C) 'Total'")
The result table:
| Month | Total |
|-------+---------|
| 6 | -150.99 |
| 7 | -165.93 |
The month should be 7 and 8, but actually it return 6 and 7.
As the documentation says:
Returns the zero-based month value from a date or datetime value. For example: month(date "2009-02-05") returns 1. Note: the months are 0-based, so the function returns 0 for January, 1 for February, etc.
As #puts said, the index is start from 0, fix that with a offset:
=query(A:E,"select MONTH(B)+1,sum(E) where A = 'Sale' or A = 'Return' group by MONTH(B) label MONTH(B)+1 'Month',sum(E) 'Total'")

Using prior cases in case type signature

I know that discriminated unions can refer to themselves, e.g.
type Tree=
| Node of Tree
| Leaf
but is there any means to refer to other cases in the type signatures? Both of the following raise errors that "The type 'Year' is not defined" & "The type 'Month' is not defined"
type Period =
| Year of int
| Month of Year * int
| Day of Month * int
type Period' =
| Year of int
| Month of Period'.Year * int
| Day of Period'.Month * int
Is there some form of annotation or a keyword I've yet to encounter (analogous to rec) that would permit such a usage?
I think you are confused about what constitutes a union case. You cannot reference a union case as a type. I think what you're looking for is single case DUs like this:
type Year = Year of int
type Month = | Month of Year * int
type Day = Month * int
type Period =
| Year of Year
| Month of Month
| Day of Day

How can I make this match expression more concise?

Learning F# by writing blackjack. I have these types:
type Suit =
| Heart = 0
| Spade = 1
| Diamond = 2
| Club = 3
type Card =
| Ace of Suit
| King of Suit
| Queen of Suit
| Jack of Suit
| ValueCard of int * Suit
I have this function (ignoring for now that aces can have 2 different values):
let NumericValue =
function | Ace(Suit.Heart) | Ace(Suit.Spade) | Ace(Suit.Diamond) | Ace(Suit.Club) -> 11
| King(Suit.Heart) | King(Suit.Spade)| King(Suit.Diamond) | King(Suit.Club) | Queen(Suit.Heart) | Queen(Suit.Spade)| Queen(Suit.Diamond) | Queen(Suit.Club) | Jack(Suit.Heart) | Jack(Suit.Spade)| Jack(Suit.Diamond) | Jack(Suit.Club) -> 10
| ValueCard(num, x) -> num
Is there a way I can include a range or something? Like [Ace(Suit.Heart) .. Ace(Suit.Club)]. Or even better Ace(*)
You want a wildcard pattern. The spec (§7.4) says:
The pattern _ is a wildcard pattern and matches any input.
let numericValue = function
| Ace _-> 11
| King _
| Queen _
| Jack _ -> 10
| ValueCard(num, _) -> num

Resources