-
-
Notifications
You must be signed in to change notification settings - Fork 192
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ab58774
commit 43c55d8
Showing
13 changed files
with
315 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Hints | ||
|
||
## 1. Define the approval | ||
|
||
- [This page][ADT] shows how to define an algebraic data type. | ||
|
||
## 2. Define the cuisine | ||
|
||
- [This page][ADT] shows how to define an algebraic data type. | ||
|
||
## 3. Define the movie genres | ||
|
||
- [This page][ADT] shows how to define an algebraic data type. | ||
|
||
## 4. Define the activity | ||
|
||
- [This section][ADT-with-data] of the same page shows how to define an algebraic data types with associated data. | ||
|
||
## 5. Rate the activity | ||
|
||
- The best way to execute logic based on the activity's value is to use [case expressions][case-expression]. | ||
- Pattern matching an algebraic data type case provides access to its associated data. | ||
- To add an additional condition to a pattern, you can use a [guard][guards] inside a case. | ||
- If you want to catch all other possible values in one case, you can use the wildcard pattern `_`. | ||
|
||
[ADT]: https://www.schoolofhaskell.com/school/starting-with-haskell/introduction-to-haskell/2-algebraic-data-types#enumeration-types | ||
[ADT-with-data]: https://www.schoolofhaskell.com/school/starting-with-haskell/introduction-to-haskell/2-algebraic-data-types#beyond-enumerations | ||
[case-expression]: https://www.schoolofhaskell.com/school/starting-with-haskell/introduction-to-haskell/2-algebraic-data-types#case-expessions | ||
[guards]: https://learnyouahaskell.github.io/syntax-in-functions.html#guards-guards |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# Instructions | ||
|
||
In this exercise, it's Valentine's day and you are planning what to do with your partner. Your partner has lots of ideas, and is asking you to rate the ideas, in order to find the best activity. | ||
|
||
The following ideas are proposed by your partner: | ||
|
||
- Playing a board game | ||
- Chill out | ||
- Watch a movie | ||
- Go to a restaurant | ||
- Take a walk | ||
|
||
You have six tasks to help choose your Valentine's day activity. | ||
|
||
## 1. Define the approval | ||
|
||
For each idea your partner proposes, you respond with one of three options: yes, no or maybe. | ||
|
||
Define the `Approval` algebraic data type to represent these options for the following three cases: `Yes`, `No` or `Maybe`. | ||
|
||
## 2. Define the cuisines | ||
|
||
Your partner has selected two possible restaurants: one based on Korean cuisine and the other based on Turkish cuisine. | ||
|
||
Define the `Cuisine` algebraic data type to represent these restaurants as the following two cases: `Korean` or `Turkish`. | ||
|
||
## 3. Define the movie genres | ||
|
||
There are tons of movies to choose from, so to narrow things down, your partner also lists their preferred genre. | ||
|
||
Define the `Genre` algebraic data type to represent the following genres cases: `Crime`, `Horror`, `Romance` or `Thriller`. | ||
|
||
## 4. Define the activity | ||
|
||
As mentioned, your partner has come up with five possible activities: playing a board game, chill out, watch a movie, go to a restaurant and taking a walk. | ||
|
||
Define the `Activity` algebraic data type to represent these activity types: | ||
|
||
- `BoardGame`: no associated data. | ||
- `Chill`: no associated data. | ||
- `Movie`: has its `Genre` as associated data. | ||
- `Restaurant`: has its `Cuisine` as associated data. | ||
- `Walk`: has an `Int` representing the number of kilometers to walk as associated data. | ||
|
||
## 5. Rate the activity | ||
|
||
Finally, you're ready to rate your partner's ideas. This is how you feel about your partner's idea: | ||
|
||
- Playing a board game: no. | ||
- Chill out: no. | ||
- Watch a movie: yes if it is a romantic movie; otherwise, no. | ||
- Go to a restaurant: yes if the cuisine is Korean, maybe if it is Turkish. | ||
- Take a walk: yes if the walk is less than three kilometers; maybe if it is between three and five kilometers; otherwise, no. | ||
|
||
Implement a function named `rateActivity` that takes an `Activity` value and returns the `Approval` based on the above sentiments. For example: | ||
|
||
```haskell | ||
rateActivity (Restaurant Turkish) | ||
-- -> Maybe | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Introduction | ||
|
||
An Algebraic Data Type (ADT) represents a fixed number of named cases. Each value of an ADT corresponds to exactly one of the named cases. | ||
|
||
An ADT is defined using the `data` keyword, with cases separated by pipe (`|`) characters. If none of the cases have data associated with them the ADT is similar to what other languages usually refer to as an _enumeration_ (or _enum_). | ||
|
||
```haskell | ||
data Season | ||
= Spring | ||
| Summer | ||
| Autumn | ||
| Winter | ||
``` | ||
|
||
Each case of an ADT can optionally have data associated with it, and different cases can have different types of data. When the case has data associated, a constructor is required. | ||
|
||
```haskell | ||
data Number | ||
= NInt Int --'NInt' is the constructor for an Int Number. | ||
| NFloat Float --'NFloat' is the constructor for an Float Number. | ||
| Invalid --'Invalid' does not have data associated to it. | ||
``` | ||
|
||
Creating a value for a specific case can be done by referring to its name (e.g, `NInt 22`). As case names are just constructor functions, associated data can be passed as a regular function argument. | ||
|
||
ADTs have _structural equality_, which means that two values for the same case and with the same (optional) data are equivalent. | ||
|
||
While one can use `if/else` expressions to work with ADTs, the recommended way to work with them is through pattern matching using _case_ statement: | ||
|
||
```haskell | ||
add1 :: Number -> String | ||
add1 number = | ||
case number of | ||
NInt i -> show (i + 1) | ||
NFloat f -> show (f + 1.0) | ||
Invalid -> error "Invalid input" | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Teaches the basics of defining data types, and we found that people usually learn best when they have to write things from scratch. | ||
Thus, the stub lacks the data type definitions for the tests. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"blurb": "Learn about algebraic data types by deciding what activity to surprise your partner with on Valentines Day.", | ||
"authors": [ | ||
"pwadsworth" | ||
], | ||
"forked_from": [ | ||
"fsharp/valentines-day" | ||
], | ||
"files": { | ||
"solution": [ | ||
"src/ValentinesDay.hs", | ||
"package.yaml" | ||
], | ||
"test": [ | ||
"test/Tests.hs" | ||
], | ||
"exemplar": [ | ||
".meta/exemplar/src/ValentinesDay.hs" | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Design | ||
|
||
## Learning objectives | ||
|
||
- Know what [Algebraic Data Types][ADT] (ADT) are. | ||
- Know how ADTs are different from enums. | ||
- Know how to define ADT, with and without data. | ||
- Know how to pattern match on ADTs using [case expressions][case-expression]. | ||
|
||
## Out of scope | ||
|
||
- Recursive ADT. | ||
- Single type wrapper ADT. | ||
- Active patterns. | ||
- Adding members to ADT. | ||
- `function` pattern shorthand notation. | ||
|
||
## Concepts | ||
|
||
- `Algebraic Data Types`: know what ADTs are; know how ADTs are different from enums; know how to define an ADT, with and without data; know how to pattern match on ADTs. | ||
|
||
## Prerequisites | ||
|
||
- `basics`: defining functions and scoping and using integers. | ||
- `pattern-matching`: know how to do pattern matching. | ||
|
||
[ADT]: https://www.schoolofhaskell.com/school/starting-with-haskell/introduction-to-haskell/2-algebraic-data-types#enumeration-types | ||
[case-expression]: https://www.schoolofhaskell.com/school/starting-with-haskell/introduction-to-haskell/2-algebraic-data-types#case-expessions |
18 changes: 18 additions & 0 deletions
18
exercises/concept/valentines-day/.meta/exemplar/package.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
name: valentines-day | ||
version: 1.0.0.0 | ||
|
||
dependencies: | ||
- base | ||
|
||
library: | ||
exposed-modules: ValentinesDay | ||
source-dirs: src | ||
ghc-options: -Wall | ||
|
||
tests: | ||
test: | ||
main: Tests.hs | ||
source-dirs: test | ||
dependencies: | ||
- valentines-day | ||
- hspec |
35 changes: 35 additions & 0 deletions
35
exercises/concept/valentines-day/.meta/exemplar/src/ValentinesDay.hs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
module ValentinesDay (rateActivity, Approval (..), Cuisine (..), Genre (..), Activity (..)) where | ||
|
||
data Approval | ||
= Yes | ||
| No | ||
| Maybe | ||
|
||
data Cuisine | ||
= Korean | ||
| Turkish | ||
|
||
data Genre | ||
= Crime | ||
| Horror | ||
| Romance | ||
| Thriller | ||
|
||
data Activity | ||
= BoardGame | ||
| Chill | ||
| Movie Genre | ||
| Restaurant Cuisine | ||
| Walk Int | ||
|
||
rateActivity :: Activity -> Approval | ||
rateActivity activity = | ||
case activity of | ||
Restaurant Korean -> Yes | ||
Restaurant Turkish -> Maybe | ||
Movie Romance -> Yes | ||
Movie _ -> No | ||
Walk kilometers | ||
| kilometers < 3 -> Yes | ||
| kilometers < 5 -> Maybe | ||
_ -> No |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
name: valentines-day | ||
version: 1.0.0.0 | ||
|
||
dependencies: | ||
- base | ||
|
||
library: | ||
exposed-modules: ValentinesDay | ||
source-dirs: src | ||
ghc-options: -Wall | ||
|
||
|
||
tests: | ||
test: | ||
main: Tests.hs | ||
source-dirs: test | ||
dependencies: | ||
- valentines-day | ||
- hspec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
module ValentinesDay where | ||
|
||
-- Define the function and required algebraic data types (ADT) below. | ||
|
||
data Approval = ImplementApproval | ||
|
||
data Cuisine = ImplementCuisine | ||
|
||
data Genre = ImplementGenre | ||
|
||
data Activity = ImplementActivity | ||
|
||
rateActivity :: Activity -> Approval | ||
rateActivity activity = error "Implement rateActivity" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
resolver: lts-18.14 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import Test.Hspec (describe, hspec, it) | ||
import ValentinesDay (Activity (..), Approval (..), Cuisine (..), Genre (..), rateActivity) | ||
|
||
main :: IO () | ||
main = hspec $ | ||
describe "ValentinesDay" $ do | ||
it "chill rated no" $ | ||
case rateActivity Chill of | ||
No -> True | ||
_ -> False | ||
it "board game rated no" $ | ||
case rateActivity BoardGame of | ||
No -> True | ||
_ -> False | ||
it "crime movie rated no" $ | ||
case rateActivity (Movie Crime) of | ||
No -> True | ||
_ -> False | ||
it "horror movie rated no" $ | ||
case rateActivity (Movie Horror) of | ||
No -> True | ||
_ -> False | ||
it "romance movie rated yes" $ | ||
case rateActivity (Movie Romance) of | ||
Yes -> True | ||
_ -> False | ||
it "thriller movie rated no" $ | ||
case rateActivity (Movie Thriller) of | ||
No -> True | ||
_ -> False | ||
it "korean restaurant rated no" $ | ||
case rateActivity (Restaurant Korean) of | ||
Yes -> True | ||
_ -> False | ||
it "turkish restaurant rated maybe" $ | ||
case rateActivity (Restaurant Turkish) of | ||
Maybe -> True | ||
_ -> False |