1
1
mirror of https://github.com/qfpl/applied-fp-course.git synced 2024-11-23 03:44:45 +03:00

Documentation updates. Removed some comments

This commit is contained in:
Sean Chalmers 2017-09-06 10:15:24 +10:00
parent 0dbad01d36
commit 71e9982e08
10 changed files with 35 additions and 32 deletions

View File

@ -44,7 +44,9 @@ data Error = Error
-- wrong thing with what we meant to be used as text or JSON etc.
data ContentType = ContentType
-- The ``ContentType`` constructors don't match what is required for the header
-- information, so write a function that will take our ``ContentType`` and
-- produce the correct value for the header.
renderContentType
:: ContentType
-> ByteString

View File

@ -8,3 +8,8 @@ packages. There may also be, depending on your level of interest, some external
reading for later as well.
Start in ``src/FirstApp/Conf.hs``.
The packages we will use for this are:
- [Aeson](http://hackage.haskell.org/package/aeson)
- [Optparse Applicative](http://hackage.haskell.org/package/optparse-applicative)

View File

@ -74,9 +74,6 @@ data ContentType
= PlainText
| JSON
-- 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

View File

@ -1,7 +1,8 @@
# Level 04
We're going to add some tests to our application! Types are awesome, tests are
pretty good. Types AND tests is pretty much perfect.
In this exercise we're going to add some tests to our application. Because types
are awesome, and tests are pretty good. But types AND tests is pretty much
perfect.
These tests will not be awe inspiring, this exercise is primarily to introduce
you to adding tests to your Haskell application. The setup of the Cabal file is
@ -15,9 +16,9 @@ Start in ``tests/Test.hs``.
#### Aside: Tool Introduction - ghcid
Additionally we'd like to introduce a command line tool that we find quite
useful for Haskell development; [ghcid]. This is a very lightweight tool that
works for any project with a functioning cabal setup.
Additionally we'd like to introduce a command line tool that you may find useful
for Haskell development; [ghcid]. This is a very lightweight tool that works for
any project with a functioning cabal setup.
If you would like to use it, consult its documentation for how to install it,
and then in an spare open terminal window, navigate to the root of the Haskell

View File

@ -94,6 +94,9 @@ executable level04
-- Base language which the package is written in.
default-language: Haskell2010
-- This is the declaration of a test-suite for your application. You may have
-- multiple test suites in a single application, provided they are named
-- differently.
test-suite level04-tests
default-language: Haskell2010
type: exitcode-stdio-1.0

View File

@ -126,7 +126,7 @@ parseJSONConfigFile fp = do
toPartialConf cObj = PartialConf
( fromJsonObjWithKey "port" Port cObj )
( fromJsonObjWithKey "helloMsg" helloFromStr cObj )
-- Use bracket to save ourselves from horrible exceptions.
readObject
:: IO (Maybe Aeson.Object)
readObject = bracketOnError

View File

@ -48,7 +48,7 @@ closeDb =
error "closeDb not implemented"
-- Due to the way our application is designed, we have a slight SQL injection
-- risk because we pull the Table name from the Conf. Write a function that
-- risk because we pull the `Table` from the `Conf`. Write a function that
-- attempts to mitigate that risk a bit, by handling replacement of a place-
-- holder value in a given Query. We should be able to write the query and pass
-- it through this function and everything is will be taken care of for us.
@ -71,16 +71,16 @@ initDb
initDb fp tab =
error "initDb not implemented"
where
-- Query has a IsString instance so you can write straight strings like this
-- and it will convert them into a Query type, use '?' as place-holders for
-- Query has a `IsString` instance so you can write straight strings like this
-- and it will convert them into a `Query` type, use '?' as place-holders for
-- ORDER DEPENDENT interpolation.
createTableQ = withTable tab
"CREATE TABLE IF NOT EXISTS $$tablename$$ (id INTEGER PRIMARY KEY, topic TEXT, comment TEXT, time INTEGER)"
-- Note that we don't store the Comment type in the DB, it is the type we build
-- Note that we don't store the `Comment` in the DB, it is the type we build
-- to send to the outside world. We will be loading our `DbComment` type from
-- the FirstApp.DB.Types module before converting trying to convert it to a
-- Comment.
-- `Comment`.
getComments
:: FirstAppDB
-> Topic

View File

@ -17,7 +17,6 @@ module FirstApp.DB.PostgreSQL where
-- import FirstApp.Types
-- -- newtype all the things!!
-- newtype Table = Table
-- { getTableName :: Text }
-- deriving Show

View File

@ -38,12 +38,12 @@ newtype Topic = Topic Text
newtype CommentText = CommentText Text
deriving (Show, ToJSON)
-- This is the Comment record that we will be sending to users, it's a simple
-- record type, containing an Int, Topic, CommentText, and UTCTime. However
-- notice that we've also derived the Generic type class instance as well. This
-- saves us some effort when it comes to creating encoding/decoding instances.
-- Since our types are all simple types at the end of the day, we're able to let
-- GHC do the work.
-- This is the `Comment` record that we will be sending to users, it's a simple
-- record type, containing an `Int`, `Topic`, `CommentText`, and `UTCTime`.
-- However notice that we've also derived the `Generic` type class instance as
-- well. This saves us some effort when it comes to creating encoding/decoding
-- instances. Since our types are all simple types at the end of the day, we're
-- able to let GHC do the work.
newtype CommentId = CommentId Int
deriving (Eq, Show, ToJSON)
@ -57,9 +57,9 @@ data Comment = Comment
deriving ( Show, Generic )
instance ToJSON Comment where
-- This is one place where we can take advantage of our Generic instance.
-- This is one place where we can take advantage of our `Generic` instance.
-- Aeson already has the encoding functions written for anything that
-- implements the Generic typeclass. So we don't have to write our encoding,
-- implements the `Generic` typeclass. So we don't have to write our encoding,
-- we ask Aeson to construct it for us.
toEncoding = A.genericToEncoding opts
where
@ -78,9 +78,9 @@ instance ToJSON Comment where
-> String
modFieldLabel = error "modFieldLabel not implemented"
-- For safety we take our stored DbComment and try to construct a Comment that
-- we would be okay with showing someone. However unlikely it may be, this is a
-- nice method for separating out the back and front end of a web app and
-- For safety we take our stored `DbComment` and try to construct a `Comment`
-- that we would be okay with showing someone. However unlikely it may be, this
-- is a nice method for separating out the back and front end of a web app and
-- providing greater guarantees about data cleanliness.
fromDbComment
:: DbComment
@ -129,16 +129,13 @@ data Error
= UnknownRoute
| EmptyCommentText
| EmptyTopic
-- | DBError SQLiteResponse
-- We need another constructor for our DB error types.
deriving Show
data ContentType
= PlainText
| JSON
-- 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

View File

@ -131,6 +131,5 @@ data ContentType
renderContentType
:: ContentType
-> ByteString
-- renderContentType = error "renderContentType not implemented"
renderContentType PlainText = "text/plain"
renderContentType JSON = "application/json"