-
Notifications
You must be signed in to change notification settings - Fork 0
feat: solutions chapter 3 #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -343,7 +343,13 @@ Define the Book product data type. You can take inspiration from our description | |
| of a book, but you are not limited only by the book properties we described. | ||
| Create your own book type of your dreams! | ||
| -} | ||
|
|
||
| data Book = NewBook | ||
| { bookTitle :: String | ||
| , bookAutor :: String | ||
| , bookPages :: Int | ||
| , bookPrice :: Int | ||
| , bookYear :: Int | ||
| } | ||
| {- | | ||
| =⚔️= Task 2 | ||
|
|
||
|
|
@@ -373,6 +379,23 @@ after the fight. The battle has the following possible outcomes: | |
| doesn't earn any money and keeps what they had before. | ||
|
|
||
| -} | ||
| data Knight = NewKnight | ||
| { knightHealth :: Int | ||
| , knightAttack :: Int | ||
| , knightGold :: Int | ||
| } deriving (Show) | ||
|
|
||
| data Monster = NewMonster | ||
| { monsterHealth :: Int | ||
| , monsterAttack :: Int | ||
| , monsterGold :: Int | ||
| } deriving (Show) | ||
|
|
||
| fight :: Knight -> Monster -> Int | ||
| fight knight monster | ||
| | monsterHealth monster - knightAttack knight <= 0 = knightGold knight + monsterGold monster | ||
| | knightHealth knight - monsterAttack monster <= 0 = -1 | ||
| | otherwise = knightGold knight | ||
|
|
||
| {- | | ||
| =🛡= Sum types | ||
|
|
@@ -459,6 +482,7 @@ and provide more flexibility when working with data types. | |
| Create a simple enumeration for the meal types (e.g. breakfast). The one who | ||
| comes up with the most number of names wins the challenge. Use your creativity! | ||
| -} | ||
| data Meal = Breakfast | Frühstück | Brunch | Lunch | Dinner | Supper | Snack | OnlyWater | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧀 🍨 🧊
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's the second German breakfast 🥳 |
||
|
|
||
| {- | | ||
| =⚔️= Task 4 | ||
|
|
@@ -479,7 +503,40 @@ After defining the city, implement the following functions: | |
| complicated task, walls can be built only if the city has a castle | ||
| and at least 10 living people inside | ||
| -} | ||
|
|
||
| data City = City | ||
| { cityCastle :: Castle | ||
| , cityMain :: MainBuilding | ||
| , cityHouses :: [House] | ||
| } | ||
|
|
||
| data Castle = None | OnlyCastle | CastleWithWalls | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The task tells that the castle should have a name. In this case, it can be a Could you guess, what functions would need patching in case of the type modifications? 🙂
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had read: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No worries, it's our bad that the wording wasn't clear! |
||
|
|
||
| data MainBuilding = Church | Library | ||
| data House = One | Two | Three | Four | ||
|
|
||
| countPeople :: House -> Int | ||
| countPeople house = case house of | ||
| One -> 1 | ||
| Two -> 2 | ||
| Three -> 3 | ||
| Four -> 4 | ||
|
|
||
| buildCastle :: City -> City | ||
| buildCastle city = case cityCastle city of | ||
| None -> city { cityCastle = OnlyCastle } | ||
| _ -> city | ||
|
|
||
| buildHouse :: House -> City -> City | ||
| buildHouse house city = | ||
| city { cityHouses = house : cityHouses city } | ||
|
|
||
| buildWalls :: City -> City | ||
| buildWalls city = case cityCastle city of | ||
| OnlyCastle -> | ||
| if sum (map countPeople (cityHouses city)) >= 10 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice combination of the standard functions 👍🏼 |
||
| then city { cityCastle = CastleWithWalls } | ||
| else city | ||
| _ -> city | ||
| {- | ||
| =🛡= Newtypes | ||
|
|
||
|
|
@@ -560,37 +617,39 @@ introducing extra newtypes. | |
| 🕯 HINT: if you complete this task properly, you don't need to change the | ||
| implementation of the "hitPlayer" function at all! | ||
| -} | ||
|
|
||
| newtype Health = Health Int | ||
| newtype Armor = Armor Int | ||
| newtype Attack = Attack Int | ||
| newtype Dexterity = Dexterity Int | ||
| newtype Strength = Strength Int | ||
| newtype Damage = Damage Int | ||
| newtype Defense = Defense Int | ||
|
|
||
| data Player = Player | ||
| { playerHealth :: Int | ||
| , playerArmor :: Int | ||
| , playerAttack :: Int | ||
| , playerDexterity :: Int | ||
| , playerStrength :: Int | ||
| { playerHealth :: Health | ||
| , playerArmor :: Armor | ||
| , playerAttack :: Attack | ||
| , playerDexterity :: Dexterity | ||
| , playerStrength :: Strength | ||
| } | ||
|
|
||
| calculatePlayerDamage :: Int -> Int -> Int | ||
| calculatePlayerDamage attack strength = attack + strength | ||
| calculatePlayerDamage :: Attack -> Strength -> Damage | ||
| calculatePlayerDamage (Attack attack) (Strength strength) = Damage (attack + strength) | ||
|
|
||
| calculatePlayerDefense :: Int -> Int -> Int | ||
| calculatePlayerDefense armor dexterity = armor * dexterity | ||
| calculatePlayerDefense :: Armor -> Dexterity -> Defense | ||
| calculatePlayerDefense (Armor armor) (Dexterity dexterity) = Defense (armor * dexterity) | ||
|
|
||
| calculatePlayerHit :: Int -> Int -> Int -> Int | ||
| calculatePlayerHit damage defense health = health + defense - damage | ||
| calculatePlayerHit :: Damage -> Defense -> Health -> Health | ||
| calculatePlayerHit (Damage damage) (Defense defense) (Health health) = Health (health + defense - damage) | ||
|
|
||
| -- The second player hits first player and the new first player is returned | ||
| hitPlayer :: Player -> Player -> Player | ||
| hitPlayer player1 player2 = | ||
| let damage = calculatePlayerDamage | ||
| (playerAttack player2) | ||
| (playerStrength player2) | ||
| defense = calculatePlayerDefense | ||
| (playerArmor player1) | ||
| (playerDexterity player1) | ||
| newHealth = calculatePlayerHit | ||
| damage | ||
| defense | ||
| (playerHealth player1) | ||
| in player1 { playerHealth = newHealth } | ||
| let damage = calculatePlayerDamage (playerAttack player2) (playerStrength player2) | ||
| defense = calculatePlayerDefense (playerArmor player1) (playerDexterity player1) | ||
| newHealth = calculatePlayerHit damage defense (playerHealth player1) | ||
| in player1 { playerHealth = newHealth } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice work on newtypes! 🏅 Newtypes are one very important feature in Haskell 👍 |
||
|
|
||
| {- | | ||
| =🛡= Polymorphic data types | ||
|
|
@@ -752,7 +811,15 @@ parametrise data types in places where values can be of any general type. | |
| 🕯 HINT: 'Maybe' that some standard types we mentioned above are useful for | ||
| maybe-treasure ;) | ||
| -} | ||
|
|
||
| data TreasureChest x = TreasureChest | ||
| { treasureChestGold :: Int | ||
| , treasureChestLoot :: x | ||
| } | ||
|
|
||
| data DragonLair treasure power = DragonLair | ||
| { dragonLairChest :: Maybe (TreasureChest treasure) | ||
| , dragonLairDragonPower :: power | ||
| } | ||
| {- | ||
| =🛡= Typeclasses | ||
|
|
||
|
|
@@ -907,9 +974,25 @@ Implement instances of "Append" for the following types: | |
| ✧ *(Challenge): "Maybe" where append is appending of values inside "Just" constructors | ||
|
|
||
| -} | ||
|
|
||
| newtype Gold = Gold Int | ||
|
|
||
| class Append a where | ||
| append :: a -> a -> a | ||
|
|
||
| instance Append Gold where | ||
| append :: Gold -> Gold -> Gold | ||
| append (Gold x) (Gold y) = Gold (x + y) | ||
|
|
||
| instance Append [a] where | ||
| append :: [a] -> [a] -> [a] | ||
| append = (++) | ||
|
|
||
| instance Append a => Append (Maybe a) where | ||
| append :: Maybe a -> Maybe a -> Maybe a | ||
| append Nothing mx = mx | ||
| append mx Nothing = mx | ||
| append (Just x) (Just y) = Just (append x y) | ||
|
|
||
| {- | ||
| =🛡= Standard Typeclasses and Deriving | ||
|
|
@@ -970,7 +1053,21 @@ implement the following functions: | |
|
|
||
| 🕯 HINT: to implement this task, derive some standard typeclasses | ||
| -} | ||
| data Weekday = Sat | Sun | Mon | Tue | Wed | Thu | Fri deriving (Show, Eq, Enum, Bounded) | ||
|
|
||
| isWeekend :: Weekday -> Bool | ||
| isWeekend weekday = case weekday of | ||
| Sat -> True | ||
| Sun -> True | ||
| _ -> False | ||
|
|
||
| nextDay :: Weekday -> Weekday | ||
| nextDay weekday | ||
| | weekday == maxBound = minBound | ||
| | otherwise = succ weekday | ||
|
|
||
| daysToParty :: Weekday -> Int | ||
| daysToParty weekday = fromEnum Fri - fromEnum weekday | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would show the shortest distance to
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I changed the regular order of days because of this, but I am aware that this is a cheat 😰 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, this one way to do it, but I agree, that this looks like a cheat 😄 You can apply the knowledge that we know exactly that there are 7 days in a week. So we can just calculate everything by Let's look how it would work: ghci> mod (5) 7
5
ghci> mod (-1) 7
6Looks like just what we need! |
||
| {- | ||
| =💣= Task 9* | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤑 💰