diff --git a/concepts/basics/.meta/config.json b/concepts/basics/.meta/config.json index 42d9bfb13..3c56e6171 100644 --- a/concepts/basics/.meta/config.json +++ b/concepts/basics/.meta/config.json @@ -1,6 +1,7 @@ { "authors": [ - "pwadsworth" + "pwadsworth", + "meatball133" ], "blurb": "Learn the basic syntax of a Haskell file" } diff --git a/concepts/basics/about.md b/concepts/basics/about.md index 1fa46a718..db6018f97 100644 --- a/concepts/basics/about.md +++ b/concepts/basics/about.md @@ -1,37 +1,47 @@ -# Haskell Syntax Basics +# Basic -## Constants and functions +Haskell is a functional programming language, there functions are treated as first-class citizens. +This means that functions can be passed as arguments to other functions, returned as values from other functions, and assigned to variables. -Haskell programs are composed of definitions and expressions. +## Functions -A constant value is defined with `name = expression`. +Functions in Haskell are defined using the `=` operator. +The name of the function is followed by its arguments, separated by spaces. +This is quite different from most other languages where the function name is followed by parentheses containing the arguments separated by commas. ```haskell -five = 5 - -six = 3 + 3 +add number1 number2 = number1 + number2 ``` -Functions are defined with `name parameters... = expression`, parameters being only separated by space. +Haskell is a statically typed language, the ghc compiler can infer the types of the arguments and the return value. +However, it is a good practice to specify the types of the arguments and the return value. +To specify the type of a function, we use the `::` operator. +The name of the function is followed by the `::` operator, then the type of the arguments separated by `->`, the last type is the return value. ```haskell +justNumber :: Int +justNumber = 42 + +add :: Int -> Int -> Int add number1 number2 = number1 + number2 ``` -Invoking a function is also an expression and is done by specifying its name and passing arguments for each of the function's parameters, separated by spaces, just like for function definitions. +## Invoking functions + +To invoke a function, we write the function name followed by the arguments separated by spaces. ```haskell -five = add 2 3 +add 1 2 ``` -Parentheses can be used to specify the order of evaluation of an expression. +When passing a function as an argument to another function, we can have to use parentheses to specify the order of evaluation. ```haskell -six = add 2 (1 * 4) - -twelve = add 2 1 * 4 +add (add 1 2) 3 ``` +There 1 2 is evaluated first, then the result is passed to the outer add function, so the outer add function recives two arguments. + ## Indentation / significant whitespace Haskell uses whitespaces and indentation to specify code boundaries. diff --git a/concepts/basics/introduction.md b/concepts/basics/introduction.md index 1fa46a718..db6018f97 100644 --- a/concepts/basics/introduction.md +++ b/concepts/basics/introduction.md @@ -1,37 +1,47 @@ -# Haskell Syntax Basics +# Basic -## Constants and functions +Haskell is a functional programming language, there functions are treated as first-class citizens. +This means that functions can be passed as arguments to other functions, returned as values from other functions, and assigned to variables. -Haskell programs are composed of definitions and expressions. +## Functions -A constant value is defined with `name = expression`. +Functions in Haskell are defined using the `=` operator. +The name of the function is followed by its arguments, separated by spaces. +This is quite different from most other languages where the function name is followed by parentheses containing the arguments separated by commas. ```haskell -five = 5 - -six = 3 + 3 +add number1 number2 = number1 + number2 ``` -Functions are defined with `name parameters... = expression`, parameters being only separated by space. +Haskell is a statically typed language, the ghc compiler can infer the types of the arguments and the return value. +However, it is a good practice to specify the types of the arguments and the return value. +To specify the type of a function, we use the `::` operator. +The name of the function is followed by the `::` operator, then the type of the arguments separated by `->`, the last type is the return value. ```haskell +justNumber :: Int +justNumber = 42 + +add :: Int -> Int -> Int add number1 number2 = number1 + number2 ``` -Invoking a function is also an expression and is done by specifying its name and passing arguments for each of the function's parameters, separated by spaces, just like for function definitions. +## Invoking functions + +To invoke a function, we write the function name followed by the arguments separated by spaces. ```haskell -five = add 2 3 +add 1 2 ``` -Parentheses can be used to specify the order of evaluation of an expression. +When passing a function as an argument to another function, we can have to use parentheses to specify the order of evaluation. ```haskell -six = add 2 (1 * 4) - -twelve = add 2 1 * 4 +add (add 1 2) 3 ``` +There 1 2 is evaluated first, then the result is passed to the outer add function, so the outer add function recives two arguments. + ## Indentation / significant whitespace Haskell uses whitespaces and indentation to specify code boundaries. diff --git a/exercises/concept/lucians-luscious-lasagna/.docs/hints.md b/exercises/concept/lucians-luscious-lasagna/.docs/hints.md index 3e2c107b8..d28386dd0 100644 --- a/exercises/concept/lucians-luscious-lasagna/.docs/hints.md +++ b/exercises/concept/lucians-luscious-lasagna/.docs/hints.md @@ -1,8 +1,45 @@ -# General +# Hints -- Basic numbers operators are described in the Haskell [GHC.Num module documentation](https://hackage.haskell.org/package/base-4.16.0.0/docs/GHC-Num.html). But you might prefer a more easily digestable [basic introduction.](https://www.tutorialspoint.com/haskell/haskell_basic_operators.htm) +## General -# Modules and Indentation +- An [integer value][integers] can be defined as one or more consecutive digits. +- [String][string] literals are a sequence of characters surrounded by double quotes. -- [Declaring modules](https://learnyouahaskell.github.io/modules#making-our-own-modules) -- [Indentation rules](https://en.wikibooks.org/wiki/Haskell/Indentation) +## 1. Define the expected oven time in minutes + +- You need to define a [function][functions] without any arguments. +- You need to return an [integer][integers]. + +## 2. Calculate the remaining oven time in minutes + +- You need to define a [function][functions] with a single argument. +- You have to return from a function. +- The function's argument is an [integer][integers]. +- You can use the [mathematical operator for subtraction][operators] to subtract values. + +## 3. Calculate the preparation time in minutes + +- You need to define a [function][functions] with a single argument. +- You have to return from a function. +- The function's argument is an [integer][integers]. +- You can use the [mathematical operator for multiplication][operators] to multiply values. + +## 4. Calculate the total working time in minutes + +- You need to define a [function][functions] with two arguments. +- You have to return an integer from a function. +- The function's argument is an [integer][integers]. +- You can invoke one of the other functions you've defined previously. +- You can use the [mathematical operator for addition][operators] to add values. + +## 5. Create a notification that the lasagna is ready + +- You need to define a [function][functions] without any arguments. +- You need to return a [string][string]. + +TODO CHANGE TO HASKELL LINKS: + +[functions]: https://www.haskell.org/tutorial/functions.html +[operators]:https://www.tutorialspoint.com/haskell/haskell_basic_operators.htm +[integers]: https://hackage.haskell.org/package/base/docs/Data-Int.html +[string]: https://hackage.haskell.org/package/base/docs/Data-String.html \ No newline at end of file diff --git a/exercises/concept/lucians-luscious-lasagna/.docs/instructions.md b/exercises/concept/lucians-luscious-lasagna/.docs/instructions.md index 1e963a8d4..41a75b9b7 100644 --- a/exercises/concept/lucians-luscious-lasagna/.docs/instructions.md +++ b/exercises/concept/lucians-luscious-lasagna/.docs/instructions.md @@ -2,31 +2,51 @@ In this exercise you're going to write some code to help you cook a brilliant lasagna from your favorite cooking book. -You have three tasks, all related to the time spent cooking the lasagna. +You have five tasks, all related to the time spent cooking the lasagna. ## 1. Define the expected oven time in minutes -Define the `expectedMinutesInOven` constant to check how many minutes the lasagna should be in the oven. According to the cooking book, the expected oven time in minutes is 40: +Define the `expectedMinutesInOven` function that does not take any arguments and returns how many minutes the lasagna should be in the oven. +According to the cooking book, the expected oven time in minutes is 40: -```Haskell +```haskell expectedMinutesInOven - --> 40 +-- -> 40 ``` -## 2. Calculate the preparation time in minutes +## 2. Calculate the remaining oven time in minutes -Define the `preparationTimeInMinutes` function that takes the number of layers you added to the lasagna as a parameter and returns how many minutes you spent preparing the lasagna, assuming each layer takes you 2 minutes to prepare. +Define the `remainingMinutesInOven` function that takes the actual minutes the lasagna has been in the oven as an argument and returns how many minutes the lasagna still has to remain in the oven, based on the expected oven time in minutes from the previous task. -```Haskell +```haskell +remainingMinutesInOven 30 +-- -> 10 +``` + +## 3. Calculate the preparation time in minutes + +Define the `preparationTimeInMinutes` function that takes the number of layers you added to the lasagna as an argument and returns how many minutes you spent preparing the lasagna, assuming each layer takes you 2 minutes to prepare. + +```haskell preparationTimeInMinutes 3 - --> 6 +-- -> 6 ``` -## 3. Calculate the elapsed time in minutes +## 4. Calculate the elapsed time in minutes -Define the `elapsedTimeInMinutes` function that takes two parameters: the first parameter is the number of layers you added to the lasagna, and the second parameter is the number of minutes the lasagna has been in the oven. The function should return how many minutes you've worked on cooking the lasagna, which is the sum of the preparation time in minutes, and the time in minutes the lasagna has spent in the oven at the moment. +Define the `totalTimeInMinutes` function that takes two arguments: the first argument is the number of layers you added to the lasagna, and the second argument is the number of minutes the lasagna has been in the oven. +The function should return how many minutes in total you've worked on cooking the lasagna, which is the sum of the preparation time in minutes, and the time in minutes the lasagna has spent in the oven at the moment. -```Haskell +```haskell elapsedTimeInMinutes 3 20 - --> 26 +-- -> 26 +``` + +## 5. Create a notification that the lasagna is ready + +Define the `alarm` function that does not take any arguments and returns a message indicating that the lasagna is ready to eat. + +```haskell +alarm +-- -> "Ding!" ``` diff --git a/exercises/concept/lucians-luscious-lasagna/.docs/introduction.md b/exercises/concept/lucians-luscious-lasagna/.docs/introduction.md index 96807773f..db6018f97 100644 --- a/exercises/concept/lucians-luscious-lasagna/.docs/introduction.md +++ b/exercises/concept/lucians-luscious-lasagna/.docs/introduction.md @@ -1,37 +1,47 @@ -# Introduction +# Basic -## Constants and functions +Haskell is a functional programming language, there functions are treated as first-class citizens. +This means that functions can be passed as arguments to other functions, returned as values from other functions, and assigned to variables. -Haskell programs are composed of definitions and expressions. +## Functions -A constant value is defined with `name = expression`. +Functions in Haskell are defined using the `=` operator. +The name of the function is followed by its arguments, separated by spaces. +This is quite different from most other languages where the function name is followed by parentheses containing the arguments separated by commas. ```haskell -five = 5 - -six = 3 + 3 +add number1 number2 = number1 + number2 ``` -Functions are defined with `name parameters... = expression`, parameters being only separated by space. +Haskell is a statically typed language, the ghc compiler can infer the types of the arguments and the return value. +However, it is a good practice to specify the types of the arguments and the return value. +To specify the type of a function, we use the `::` operator. +The name of the function is followed by the `::` operator, then the type of the arguments separated by `->`, the last type is the return value. ```haskell +justNumber :: Int +justNumber = 42 + +add :: Int -> Int -> Int add number1 number2 = number1 + number2 ``` -Invoking a function is also an expression and is done by specifying its name and passing arguments for each of the function's parameters, separated by spaces, just like for function definitions. +## Invoking functions + +To invoke a function, we write the function name followed by the arguments separated by spaces. ```haskell -five = add 2 3 +add 1 2 ``` -Parentheses can be used to specify the order of evaluation of an expression. +When passing a function as an argument to another function, we can have to use parentheses to specify the order of evaluation. ```haskell -six = add 2 (1 * 4) - -twelve = add 2 1 * 4 +add (add 1 2) 3 ``` +There 1 2 is evaluated first, then the result is passed to the outer add function, so the outer add function recives two arguments. + ## Indentation / significant whitespace Haskell uses whitespaces and indentation to specify code boundaries. @@ -83,7 +93,11 @@ Multiline comments are also possible with the `{-` and `-}` pair of opening and -} ``` +## Formatting + +There is a [style guide](https://kowainik.github.io/posts/2019-02-06-style-guide), and [Stylish-Haskell](https://github.com/haskell/stylish-haskell) can be used to automatically format code. + ### Credits -This exercise introduction borrows liberally from [Learn You a Haskell for Great Good!](https://learnyouahaskell.github.io/chapters), +This concept guide borrows liberally from [Learn You a Haskell for Great Good!](https://learnyouahaskell.github.io/chapters), under [Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License](https://creativecommons.org/licenses/by-nc-sa/3.0/) diff --git a/exercises/concept/lucians-luscious-lasagna/.meta/config.json b/exercises/concept/lucians-luscious-lasagna/.meta/config.json index 34fcfe6f5..30679a054 100644 --- a/exercises/concept/lucians-luscious-lasagna/.meta/config.json +++ b/exercises/concept/lucians-luscious-lasagna/.meta/config.json @@ -1,6 +1,7 @@ { "authors": [ - "pwadsworth" + "pwadsworth", + "meatball133" ], "files": { "solution": [ @@ -18,7 +19,8 @@ ] }, "forked_from": [ - "fsharp/lucians-luscious-lasagna" + "fsharp/lucians-luscious-lasagna", + "elixir/lasagna" ], "icon": "lasagna", "blurb": "Learn the basics of Haskell by cooking Lucian's Luscious Lasagna" diff --git a/exercises/concept/lucians-luscious-lasagna/.meta/exemplar/src/LuciansLusciousLasagna.hs b/exercises/concept/lucians-luscious-lasagna/.meta/exemplar/src/LuciansLusciousLasagna.hs index d48560648..48c06aeee 100644 --- a/exercises/concept/lucians-luscious-lasagna/.meta/exemplar/src/LuciansLusciousLasagna.hs +++ b/exercises/concept/lucians-luscious-lasagna/.meta/exemplar/src/LuciansLusciousLasagna.hs @@ -1,13 +1,21 @@ -module LuciansLusciousLasagna (elapsedTimeInMinutes, expectedMinutesInOven, preparationTimeInMinutes) where +module LuciansLusciousLasagna (totalTimeInMinutes, remainingMinutesInOven, expectedMinutesInOven, preparationTimeInMinutes, alarm) where expectedMinutesInOven :: Int expectedMinutesInOven = 40 +remainingMinutesInOven :: Int -> Int +remainingMinutesInOven passedAlready = + expectedMinutesInOven - passedAlready + preparationTimeInMinutes :: Int -> Int preparationTimeInMinutes layers = 2 * layers -elapsedTimeInMinutes :: Int -> Int -> Int -elapsedTimeInMinutes layers passedAlready = +totalTimeInMinutes :: Int -> Int -> Int +totalTimeInMinutes layers passedAlready = passedAlready + preparationTimeInMinutes layers + +alarm :: String +alarm = + "DING!" \ No newline at end of file diff --git a/exercises/concept/lucians-luscious-lasagna/src/LuciansLusciousLasagna.hs b/exercises/concept/lucians-luscious-lasagna/src/LuciansLusciousLasagna.hs index a6646eacd..92ce518c0 100644 --- a/exercises/concept/lucians-luscious-lasagna/src/LuciansLusciousLasagna.hs +++ b/exercises/concept/lucians-luscious-lasagna/src/LuciansLusciousLasagna.hs @@ -1,7 +1,11 @@ -module LuciansLusciousLasagna (elapsedTimeInMinutes, expectedMinutesInOven, preparationTimeInMinutes) where +module LuciansLusciousLasagna (totalTimeInMinutes, remainingMinutesInOven, expectedMinutesInOven, preparationTimeInMinutes, alarm) where -- TODO: define the expectedMinutesInOven constant +-- TODO: define the remainingMinutesInOven function + -- TODO: define the preparationTimeInMinutes function --- TODO: define the elapsedTimeInMinutes function +-- TODO: define the totalTimeInMinutes function + +-- TODO: define the alarm constant diff --git a/exercises/concept/lucians-luscious-lasagna/test/Tests.hs b/exercises/concept/lucians-luscious-lasagna/test/Tests.hs index fc7448f3a..5d2b95603 100644 --- a/exercises/concept/lucians-luscious-lasagna/test/Tests.hs +++ b/exercises/concept/lucians-luscious-lasagna/test/Tests.hs @@ -1,13 +1,29 @@ import Test.Hspec (it, shouldBe, hspec) -import LuciansLusciousLasagna (elapsedTimeInMinutes, expectedMinutesInOven, preparationTimeInMinutes) +import LuciansLusciousLasagna (totalTimeInMinutes, remainingMinutesInOven, expectedMinutesInOven, preparationTimeInMinutes, alarm) main :: IO () main = hspec $ do - it "expectedMinutesInOven" $ do + it "expected minutes in oven" $ do expectedMinutesInOven `shouldBe` 40 - it "preparationTimeInMinutes" $ - preparationTimeInMinutes 5 `shouldBe` 10 + it "remaining minutes in oven" $ + remainingMinutesInOven 25 `shouldBe` 15 - it "elapsedTimeInMinutes" $ do - elapsedTimeInMinutes 3 20 `shouldBe` 26 + it "remaining minutes in oven, a few minutes later" $ + remainingMinutesInOven 30 `shouldBe` 10 + + it "preparation time in minutes for one layer" $ + preparationTimeInMinutes 1 `shouldBe` 2 + + it "preparation time in minutes for multiple layers" $ + preparationTimeInMinutes 4 `shouldBe` 8 + + it "total time in minutes for one layer" $ + totalTimeInMinutes 1 30 `shouldBe` 32 + + it "total time in minutes for multiple layers" $ + totalTimeInMinutes 4 8 `shouldBe` 16 + + it "notification message" $ + alarm `shouldBe` "DING!" + \ No newline at end of file