From 60d0e9246e4065cba6782ebad796f2cedf0c3606 Mon Sep 17 00:00:00 2001 From: Amos King Date: Mon, 19 Nov 2018 14:17:45 -0600 Subject: [PATCH 1/4] Update Readme to show how to run a single test When working through the code it is often nice to be able to run a single test. Amos King @adkron --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 59882a1..7d193ae 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,12 @@ On a mac: stack test ``` +## Run a single test file + +``` +stack runghc -- -isrc -itest test/Cis194/Hw/SomeSpec.hs +``` + ## Using QuickCheck in ghci :m +Test.QuickCheck From a93524dce9b655f96bb64f1ec4c28e2e6360c057 Mon Sep 17 00:00:00 2001 From: Amos L King Date: Tue, 20 Nov 2018 10:45:24 -0600 Subject: [PATCH 2/4] HW 2 init I have an issue with `buildMessage` not being exhaustive because it needs to match on an empty map. I really didn't like building all this stuff in the case statement and that is why I pulled it out. I think I need to start thinking of functions returning functions and build it up as arguments get passed in. Amos King @adkron --- src/Cis194/Hw/LogAnalysis.hs | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/Cis194/Hw/LogAnalysis.hs b/src/Cis194/Hw/LogAnalysis.hs index 3adfa15..f0e9e0f 100644 --- a/src/Cis194/Hw/LogAnalysis.hs +++ b/src/Cis194/Hw/LogAnalysis.hs @@ -6,22 +6,44 @@ module Cis194.Hw.LogAnalysis where import Cis194.Hw.Log parseMessage :: String -> LogMessage -parseMessage s = Unknown s +parseMessage s = + case words s of + "E":i:ws -> buildMessage (Error (read i)) ws + "I":ws -> buildMessage Info ws + "W":ws -> buildMessage Warning ws + _ -> Unknown s + +buildMessage :: MessageType -> [String] -> LogMessage +buildMessage m (t:ws) = LogMessage m (read t) (unwords ws) parse :: String -> [LogMessage] -parse _ = [] +parse = map (parseMessage) . lines insert :: LogMessage -> MessageTree -> MessageTree +insert (Unknown _) t = t +insert l Leaf = Node Leaf l Leaf +insert n@(LogMessage _ nt _) (Node l m@(LogMessage _ mt _) r) + | nt < mt = Node (insert n l) m r + | nt > mt = Node l m (insert n r) insert _ t = t build :: [LogMessage] -> MessageTree -build _ = Leaf +build = foldr insert Leaf . reverse inOrder :: MessageTree -> [LogMessage] -inOrder _ = [] +inOrder (Node l m r) = inOrder l ++ [m] ++ inOrder r +inOrder Leaf = [] -- whatWentWrong takes an unsorted list of LogMessages, and returns a list of the -- messages corresponding to any errors with a severity of 50 or greater, -- sorted by timestamp. whatWentWrong :: [LogMessage] -> [String] -whatWentWrong _ = [] +whatWentWrong = map getString . filter isSever . inOrder . build + +isSever :: LogMessage -> Bool +isSever (LogMessage (Error s) _ _) = s >= 50 +isSever _ = False + +getString :: LogMessage -> String +getString (LogMessage _ _ s) = s +getString (Unknown s) = s From d1fce6f22c6bbac2ca4ab42d6c7420dab152c5a2 Mon Sep 17 00:00:00 2001 From: Amos L King Date: Wed, 21 Nov 2018 13:06:33 -0600 Subject: [PATCH 3/4] Updates with some review items from @glguy I really like the pattern that was used in `inOrder` that was brilliant. Thanks for the help and the pointer on matching a type constructor. Amos King @adkron --- src/Cis194/Hw/LogAnalysis.hs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/Cis194/Hw/LogAnalysis.hs b/src/Cis194/Hw/LogAnalysis.hs index f0e9e0f..e5da016 100644 --- a/src/Cis194/Hw/LogAnalysis.hs +++ b/src/Cis194/Hw/LogAnalysis.hs @@ -8,19 +8,19 @@ import Cis194.Hw.Log parseMessage :: String -> LogMessage parseMessage s = case words s of - "E":i:ws -> buildMessage (Error (read i)) ws - "I":ws -> buildMessage Info ws - "W":ws -> buildMessage Warning ws + "E":i:t:ws -> buildMessage (Error (read i)) t ws + "I":t:ws -> buildMessage Info t ws + "W":t:ws -> buildMessage Warning t ws _ -> Unknown s -buildMessage :: MessageType -> [String] -> LogMessage -buildMessage m (t:ws) = LogMessage m (read t) (unwords ws) +buildMessage :: MessageType -> String -> [String] -> LogMessage +buildMessage m t ws = LogMessage m (read t) (unwords ws) parse :: String -> [LogMessage] -parse = map (parseMessage) . lines +parse = map parseMessage . lines insert :: LogMessage -> MessageTree -> MessageTree -insert (Unknown _) t = t +insert Unknown{} t = t insert l Leaf = Node Leaf l Leaf insert n@(LogMessage _ nt _) (Node l m@(LogMessage _ mt _) r) | nt < mt = Node (insert n l) m r @@ -31,18 +31,20 @@ build :: [LogMessage] -> MessageTree build = foldr insert Leaf . reverse inOrder :: MessageTree -> [LogMessage] -inOrder (Node l m r) = inOrder l ++ [m] ++ inOrder r -inOrder Leaf = [] +inOrder t = go t [] + where + go (Node l m r) = go l . (m:) . go r + go Leaf = id -- whatWentWrong takes an unsorted list of LogMessages, and returns a list of the -- messages corresponding to any errors with a severity of 50 or greater, -- sorted by timestamp. whatWentWrong :: [LogMessage] -> [String] -whatWentWrong = map getString . filter isSever . inOrder . build +whatWentWrong = map getString . filter isSevere . inOrder . build -isSever :: LogMessage -> Bool -isSever (LogMessage (Error s) _ _) = s >= 50 -isSever _ = False +isSevere :: LogMessage -> Bool +isSevere (LogMessage (Error s) _ _) = s >= 50 +isSevere _ = False getString :: LogMessage -> String getString (LogMessage _ _ s) = s From 5a7db0ac22af62ede0c73bc96ef560fb19bf72fe Mon Sep 17 00:00:00 2001 From: Amos L King Date: Sat, 24 Nov 2018 23:06:06 -0600 Subject: [PATCH 4/4] Removes reverse by using foldl instead of foldr foldl and foldr expect arguments in different orders, but flip allows the arguments to be flipped. Amos King @adkron --- src/Cis194/Hw/LogAnalysis.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cis194/Hw/LogAnalysis.hs b/src/Cis194/Hw/LogAnalysis.hs index e5da016..c3512df 100644 --- a/src/Cis194/Hw/LogAnalysis.hs +++ b/src/Cis194/Hw/LogAnalysis.hs @@ -28,7 +28,7 @@ insert n@(LogMessage _ nt _) (Node l m@(LogMessage _ mt _) r) insert _ t = t build :: [LogMessage] -> MessageTree -build = foldr insert Leaf . reverse +build = foldl (flip insert) Leaf inOrder :: MessageTree -> [LogMessage] inOrder t = go t []