diff --git a/level02/src/FirstApp/Main.hs b/level02/src/FirstApp/Main.hs index ebc233f..6d86e38 100644 --- a/level02/src/FirstApp/Main.hs +++ b/level02/src/FirstApp/Main.hs @@ -17,9 +17,9 @@ import Data.Text.Encoding (decodeUtf8) import FirstApp.Types --- |------------------------------------------------------| --- | Don't start here, go straight to FirstApp.Types! :) | --- |------------------------------------------------------| +-- ---------------------------------------------| +-- Don't start here, go to FirstApp.Types! :) | +-- ---------------------------------------------| runApp :: IO () runApp = run 3000 app @@ -65,6 +65,7 @@ mkRequest rq = -- These helpers will take the raw request information and turn it into -- one of our data types. This means we draw a line about where the unruly outside -- world must end, and where the well-typed world of our application begins. + mkAddRequest :: Text -> LBS.ByteString @@ -75,25 +76,27 @@ mkAddRequest ti c = -- This has other benefits, we're able isolate our validation requirements into the -- smallest chunks we can manage. This allows for fantastic reuse and it also means -- that validation is not spread across the application. It is kept at the borders. + mkViewRequest :: Text -> Either Error RqType mkViewRequest = error "mkViewRequest not implemented" --- Even thought it may seem trivial or even pointless to write functions such as these --- it allows for much greater consistency across the application. - --- These are straight forward data constructors, but by doing it this way we don't --- have any snowflakes littered about the code. It also enhances our ability to --- spot larger patterns in our application, which are opportunities for abstraction. +-- Even though it may seem too trivial or even pointless to write functions such +-- as these it allows for much greater consistency across the application. +-- +-- Some of these are straight forward data constructors, but by doing it this +-- way we don't have any snowflakes littered about the code. It also enhances +-- our ability to spot larger patterns in our application, which are +-- opportunities for abstraction. mkListRequest :: Either Error RqType mkListRequest = error "mkListRequest not implemented" {-| -HALP +HALP - wording - is it useful? Alternative type sig: Either Error a @@ -112,20 +115,17 @@ mkErrorResponse mkErrorResponse _ = error "mkErrorResponse not implemented" -{-| -We'll stub these for now as the general structure and the process of reaching -this stage is the more important lesson here. - -Notice how we're only accepting our predefined request types that have the required -information already validated and prepared for use in the handling of the request. - -If we find that we need more information to handle a request, or we have a new -type of request that we'd like to handle then we simply update the RqType structure -and the compiler will let us know the affected portions of our application. - -Reduction of concerns such that each section of the application only deals with -a small piece is one of the benefits of developing in this way. --} +-- Notice how we're only accepting our predefined request types that have the +-- required information already validated and prepared for use in the handling +-- of the request. +-- +-- If we find that we need more information to handle a request, or we have a +-- new type of request that we'd like to handle then we simply update the RqType +-- structure and the compiler will let us know the affected portions of our +-- application. +-- +-- Reduction of concerns such that each section of the application only deals +-- with a small piece is one of the benefits of developing in this way. handleRequest :: RqType -> Either Error Response diff --git a/level02/src/FirstApp/Types.hs b/level02/src/FirstApp/Types.hs index 87cd866..7347163 100644 --- a/level02/src/FirstApp/Types.hs +++ b/level02/src/FirstApp/Types.hs @@ -23,23 +23,33 @@ data RqType -- types reflect when errors can be introduced into our program. Additionally -- it's useful to be able to be descriptive about what went wrong. --- So lets think about some of the basic things that can wrong with our --- program and create some values to represent that. +-- Think about some of the basic things that can wrong with our Requests and +-- building the RqTypes, and create some values to represent that. data Error +-- For now we don't need to worry about things like malformed requests or +-- invalid headers etc. -- Provide a type to list our response content types so we don't try to -- do the wrong thing with what we meant to be used as text/JSON etc. data ContentType +-- +-- The ContentType description for a header doesn't match our data definition +-- so we write a little helper function to pattern match on our ContentType +-- value and provide the correct header value. +renderContentType + :: ContentType + -> ByteString +renderContentType = + error "renderContentType not implemented" -- In Haskell the `newtype` comes with zero runtime cost. It is purely used for -- typechecking. So when you have a bare 'primitive' value, like an Int, String, or -- even [a], you can wrap it up in a `newtype` for clarity. --- The type system will check it for you, and the compiler will eliminate the cost --- once it has passed. +-- The type system will check it for you, and the compiler will eliminate the cost. -- Having specialised constructor functions for the newtypes allows you to set --- restrictions for your newtype. +-- extra restrictions for your newtype. -- Write two `newtype` definitions for `Topic` and `CommentText` that wrap a -- `Text` value @@ -52,10 +62,9 @@ data ContentType -- | --- An additional benefit of `newtype` is that we can choose to not export the --- constructor and provide a function of our own. In our case, we're not --- interested in empty `Text` values so we can eliminate them and immediately --- report an error. +-- A benefit of `newtype` is that we can choose to *not* export the constructor +-- and provide a function of our own. In our case, we're not interested in empty +-- `Text` values so we can eliminate them and immediately report an error. mkTopic :: Text -> Either Error Topic @@ -69,13 +78,6 @@ mkCommentText = error "mkCommentText not implemented" -- After you've implemented these functions, adjust the export list in the --- module declaration so your constructor functions cannot be bypassed. +-- module declaration so your constructor functions cannot be bypassed. Also +-- export the functions that let you access the inner value of the newtype. --- The ContentType description for a header doesn't match our data definition --- so we write a little helper function to pattern match on our ContentType --- value and provide the correct header value. -renderContentType - :: ContentType - -> ByteString -renderContentType = - error "renderContentType not implemented"