Skip to content

Commit 662e71b

Browse files
committed
Complete Set14
1 parent 264d126 commit 662e71b

File tree

2 files changed

+52
-19
lines changed

2 files changed

+52
-19
lines changed

Set14a.hs

+14-10
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ import qualified Data.ByteString.Lazy as BL
2828
-- greetText (T.pack "Benedict Cumberbatch") ==> "Hello, Benedict Cumber...!"
2929

3030
greetText :: T.Text -> T.Text
31-
greetText = todo
31+
greetText name
32+
| T.length name <= 15 = T.pack ("Hello, " ++ T.unpack name ++ "!")
33+
| otherwise = T.pack ("Hello, " ++ T.unpack (T.take 15 name) ++ "...!")
3234

3335
------------------------------------------------------------------------------
3436
-- Ex 2: Capitalize every second word of a Text.
@@ -40,7 +42,7 @@ greetText = todo
4042
-- ==> "WORD"
4143

4244
shout :: T.Text -> T.Text
43-
shout = todo
45+
shout text = T.unwords $ zipWith ($) (cycle [T.toUpper, id]) (T.words text)
4446

4547
------------------------------------------------------------------------------
4648
-- Ex 3: Find the longest sequence of a single character repeating in
@@ -51,8 +53,9 @@ shout = todo
5153
-- longestRepeat (T.pack "aabbbbccc") ==> 4
5254

5355
longestRepeat :: T.Text -> Int
54-
longestRepeat = todo
55-
56+
longestRepeat text
57+
| T.null text = 0
58+
| otherwise = maximum $ map T.length $ T.group text
5659
------------------------------------------------------------------------------
5760
-- Ex 4: Given a lazy (potentially infinite) Text, extract the first n
5861
-- characters from it and return them as a strict Text.
@@ -64,7 +67,7 @@ longestRepeat = todo
6467
-- takeStrict 15 (TL.pack (cycle "asdf")) ==> "asdfasdfasdfasd"
6568

6669
takeStrict :: Int64 -> TL.Text -> T.Text
67-
takeStrict = todo
70+
takeStrict n = TL.toStrict . TL.take n
6871

6972
------------------------------------------------------------------------------
7073
-- Ex 5: Find the difference between the largest and smallest byte
@@ -76,7 +79,9 @@ takeStrict = todo
7679
-- byteRange (B.pack [3]) ==> 0
7780

7881
byteRange :: B.ByteString -> Word8
79-
byteRange = todo
82+
byteRange bytes
83+
| B.null bytes = 0
84+
| otherwise = B.maximum bytes - B.minimum bytes
8085

8186
------------------------------------------------------------------------------
8287
-- Ex 6: Compute the XOR checksum of a ByteString. The XOR checksum of
@@ -97,7 +102,7 @@ byteRange = todo
97102
-- xorChecksum (B.pack []) ==> 0
98103

99104
xorChecksum :: B.ByteString -> Word8
100-
xorChecksum = todo
105+
xorChecksum = B.foldl xor 0
101106

102107
------------------------------------------------------------------------------
103108
-- Ex 7: Given a ByteString, compute how many UTF-8 characters it
@@ -114,7 +119,7 @@ xorChecksum = todo
114119
-- countUtf8Chars (B.drop 1 (encodeUtf8 (T.pack "åäö"))) ==> Nothing
115120

116121
countUtf8Chars :: B.ByteString -> Maybe Int
117-
countUtf8Chars = todo
122+
countUtf8Chars = either (const Nothing) (Just . T.length) . decodeUtf8'
118123

119124
------------------------------------------------------------------------------
120125
-- Ex 8: Given a (nonempty) strict ByteString b, generate an infinite
@@ -126,5 +131,4 @@ countUtf8Chars = todo
126131
-- ==> [0,1,2,2,1,0,0,1,2,2,1,0,0,1,2,2,1,0,0,1]
127132

128133
pingpong :: B.ByteString -> BL.ByteString
129-
pingpong = todo
130-
134+
pingpong b = BL.cycle $ BL.fromStrict b <> BL.reverse (BL.fromStrict b)

Set14b.hs

+38-9
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,17 @@ getAllQuery = Query (T.pack "SELECT account, amount FROM events;")
7676
-- NOTE! Do not add anything to the name, otherwise you'll get weird
7777
-- test failures later.
7878
openDatabase :: String -> IO Connection
79-
openDatabase = todo
79+
openDatabase f = do
80+
db <- open f
81+
execute_ db initQuery
82+
return db
8083

8184
-- given a db connection, an account name, and an amount, deposit
8285
-- should add an (account, amount) row into the database
8386
deposit :: Connection -> T.Text -> Int -> IO ()
84-
deposit = todo
87+
deposit db account amount = do
88+
execute db depositQuery (account, amount)
89+
return ()
8590

8691
------------------------------------------------------------------------------
8792
-- Ex 2: Fetching an account's balance. Below you'll find
@@ -112,7 +117,9 @@ balanceQuery :: Query
112117
balanceQuery = Query (T.pack "SELECT amount FROM events WHERE account = ?;")
113118

114119
balance :: Connection -> T.Text -> IO Int
115-
balance = todo
120+
balance db account = do
121+
rows <- query db balanceQuery [account] :: IO [[Int]]
122+
return $ sum $ map head rows
116123

117124
------------------------------------------------------------------------------
118125
-- Ex 3: Now that we have the database part covered, let's think about
@@ -144,14 +151,22 @@ balance = todo
144151
-- parseCommand [T.pack "deposit", T.pack "madoff", T.pack "123456"]
145152
-- ==> Just (Deposit "madoff" 123456)
146153

147-
data Command = Deposit T.Text Int | Balance T.Text
154+
data Command = Deposit T.Text Int | Balance T.Text | Withdraw T.Text Int
148155
deriving (Show, Eq)
149156

150157
parseInt :: T.Text -> Maybe Int
151158
parseInt = readMaybe . T.unpack
152159

153160
parseCommand :: [T.Text] -> Maybe Command
154-
parseCommand = todo
161+
parseCommand cmd
162+
| length cmd == 2 && head cmd == T.pack "balance" = Just $ Balance (cmd !! 1)
163+
| length cmd == 3 = case parseInt $ cmd !! 2 of
164+
Just amount -> case T.unpack $ head cmd of
165+
"deposit" -> Just $ Deposit (cmd !! 1) amount
166+
"withdraw" -> Just $ Withdraw (cmd !! 1) amount
167+
otherwise -> Nothing
168+
Nothing -> Nothing
169+
| otherwise = Nothing
155170

156171
------------------------------------------------------------------------------
157172
-- Ex 4: Running commands. Implement the IO operation perform that takes a
@@ -177,7 +192,17 @@ parseCommand = todo
177192
-- "0"
178193

179194
perform :: Connection -> Maybe Command -> IO T.Text
180-
perform = todo
195+
perform db cmd = case cmd of
196+
Just (Deposit account amount) -> do
197+
deposit db account amount
198+
return (T.pack "OK")
199+
Just (Balance account) -> do
200+
balance' <- balance db account
201+
return (T.pack $ show balance')
202+
Just (Withdraw account amount) -> do
203+
deposit db account (-amount)
204+
return (T.pack "OK")
205+
otherwise -> return (T.pack "ERROR")
181206

182207
------------------------------------------------------------------------------
183208
-- Ex 5: Next up, let's set up a simple HTTP server. Implement a WAI
@@ -197,7 +222,7 @@ encodeResponse t = LB.fromStrict (encodeUtf8 t)
197222
-- Remember:
198223
-- type Application = Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived
199224
simpleServer :: Application
200-
simpleServer request respond = todo
225+
simpleServer request respond = respond $ responseLBS status200 [] (encodeResponse (T.pack "BANK"))
201226

202227
------------------------------------------------------------------------------
203228
-- Ex 6: Now we finally have all the pieces we need to actually
@@ -226,7 +251,10 @@ simpleServer request respond = todo
226251
-- Remember:
227252
-- type Application = Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived
228253
server :: Connection -> Application
229-
server db request respond = todo
254+
server db request respond = do
255+
let cmd = parseCommand (pathInfo request)
256+
response <- perform db cmd
257+
respond $ responseLBS status200 [] (encodeResponse response)
230258

231259
port :: Int
232260
port = 3421
@@ -257,6 +285,7 @@ main = do
257285
-- - Open <http://localhost:3421/balance/simon> in your browser.
258286
-- You should see the text 11.
259287

288+
-- Ex 3 & Ex4
260289

261290
------------------------------------------------------------------------------
262291
-- Ex 8: Error handling. Modify the parseCommand function so that it
@@ -277,4 +306,4 @@ main = do
277306
-- - http://localhost:3421/balance
278307
-- - http://localhost:3421/balance/matti/pekka
279308

280-
309+
-- Ex 3 & Ex4

0 commit comments

Comments
 (0)