Skip to content

Add Flags Attribute concept exercise - #1387

Open
blackk-foxx wants to merge 6 commits into
exercism:mainfrom
blackk-foxx:feature/flags-enum-concept
Open

Add Flags Attribute concept exercise#1387
blackk-foxx wants to merge 6 commits into
exercism:mainfrom
blackk-foxx:feature/flags-enum-concept

Conversation

@blackk-foxx

@blackk-foxx blackk-foxx commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Introduce the Flags Attribute (aka flags-discriminated-union) concept and provide an exercise to teach it. The exercise goal is to use the Flags attribute to build a password checker capable of reporting multiple rule violations in one call.

@github-actions

Copy link
Copy Markdown
Contributor

Hello. Thanks for opening a PR on Exercism 🙂

We ask that all changes to Exercism are discussed on our Community Forum before being opened on GitHub. To enforce this, we automatically close all PRs that are submitted. That doesn't mean your PR is rejected but that we want the initial discussion about it to happen on our forum where a wide range of key contributors across the Exercism ecosystem can weigh in.

You can use this link to copy this into a new topic on the forum. If we decide the PR is appropriate, we'll reopen it and continue with it, so please don't delete your local branch.

If you're interested in learning more about this auto-responder, please read this blog post.


Note: If this PR has been pre-approved, please link back to this PR on the forum thread and a maintainer or staff member will reopen it.

@github-actions github-actions Bot closed this Jul 23, 2026
@ErikSchierboom

Copy link
Copy Markdown
Member

I'm currently away, so I don't have time to review this right now. Regarding your question: I'm positive that we have other exercises that have the same problem. Likely the discriminated unions exercises. Maybe you could check to see if that is referenced somewhere? There might be an exclude list or something.

failwith "Please implement this function"

/// Return a set of human-readable phrases indicating the meaning of the given result value.
let getStatusPhrases (result: Result<string, PasswordError>) : Set<string> =

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is returning a Set, which means that the student has to know about sets. So either it needs to be a prerequisite, or we should use a list here (which is my preference).

```

Setting a flag can be done with the bitwise OR operator (`|||`); unsetting a flag can be done with a combination of the bitwise AND operator (`&&&`) and the bitwise negation operator (`~~~`).
While checking flag's state can be done with the bitwise AND operator, one can also use the HasFlag() method.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
While checking flag's state can be done with the bitwise AND operator, one can also use the HasFlag() method.
While checking a flag's state can be done with the bitwise AND operator, one can also use the `HasFlag()` method.

Comment on lines +31 to +36

// Unset the Call flag
let lessFeatures = features &&& ~~~PhoneFeatures.Call

lessFeatures.HasFlag(PhoneFeatures.Call) // => false
lessFeatures.HasFlag(PhoneFeatures.Text) // => true

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd remove this as I feel confident student should be able to figure this out based on the above example and what is in the other introduction text.

Suggested change
// Unset the Call flag
let lessFeatures = features &&& ~~~PhoneFeatures.Call
lessFeatures.HasFlag(PhoneFeatures.Call) // => false
lessFeatures.HasFlag(PhoneFeatures.Text) // => true

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that there might be a more idiomatic F# solution here without using mutable. I'll try and come up with one/


## 2. Implement the `checkPassword` function

The `checkPassword` function checks the given password against the aforementioned rules. On failure, it indicates the rule(s) that was/were violated by encapsulating one or more of the `PasswordError` values within the result value.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each sentence should be on a separate line. And maybe we can be slightly more specific on what should be returned?

Suggested change
The `checkPassword` function checks the given password against the aforementioned rules. On failure, it indicates the rule(s) that was/were violated by encapsulating one or more of the `PasswordError` values within the result value.
The `checkPassword` function checks the given password against the aforementioned rules.
The function should return a `Result` value, where `Ok` is returned when the password satisfies all rules, and an `Error` value when it fails one or more rules.
If multiple rules fail, the `PasswordError` value should represent all those failing rules.

Or something like that.


## 3. Implement the ``getStatusPhrases` function

The `getStatusPhrases` function returns a set of strings each containing a human-readable phrase corresponding to one of the erorrs in the result returned from `checkPassword`.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned elsewhere, I'd suggest making this a simple list.

- Must have at least one digit
- Must have at least one symbol in the set !@#$%^&\*

Your solution must use a `Result` to encapsulate the success or failure status.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These instructions are specific to task 2 (the other tasks don't use results), so should probably be moved to that task (and I've already added some alternative text there).

| Text = 0b00000010
```

A `PhoneFeatures` instance with the value 0b00000011 has both its Call and Text flags set.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A `PhoneFeatures` instance with the value 0b00000011 has both its Call and Text flags set.
A `PhoneFeatures` instance with the value `0b00000011` has both its `Call` and `Text` flags set.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth adding a mention that flags can be set or unset using bitwise operators.

Comment on lines +62 to +72
[<Fact>]
[<Task(2)>]
let ``Missing symbol error with twelve mixed-case letters and digits`` () =
let expected: Result<string, PasswordError> = Error PasswordError.MissingSymbol
checkPassword "ABCDEF123ghi" |> should equal expected

[<Fact>]
[<Task(2)>]
let ``Missing digit error with twelve mixed-case letters and symbols`` () =
let expected: Result<string, PasswordError> = Error PasswordError.MissingDigit
checkPassword "ABCDEF$&*ghi" |> should equal expected

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would start with these two tests, as that allows the student to first focus on the error-returning bit, and then build on that to add the flag setting pattern to combine values. In other words: if the student would follow the current order, these tests will likely always pass without having to do any work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants