Under “Building a Basic Metrics System with IORefs”, have created a sample file with the code snippets from page 379-383 as follows:
module Metrics where
import qualified Data.Map.Strict as Map
import Data.IORef
import Data.Maybe (fromMaybe)
import Data.Time.Clock
( diffUTCTime
, getCurrentTime
, nominalDiffTimeToSeconds
)
data AppMetrics = AppMetrics
{ successCount :: Int
, failureCount :: Int
, callDuration :: Map.Map String Int
} deriving Show
metrics :: IO (IORef AppMetrics)
metrics = newIORef AppMetrics
{ successCount = 0
, failureCount = 0
, callDuration = Map.empty
}
printMetrics :: IO ()
printMetrics = metrics >>= readIORef >>= print
incrementSuccess :: IO ()
incrementSuccess =
metrics >>= flip modifyIORef incrementSuccess
where
incrementSuccess m =
m { successCount = 1 + successCount m}
successfullyPrintHello :: IO ()
successfullyPrintHello = do
print “Hello”
incrementSuccess
printHelloAndMetrics = do
successfullyPrintHello
printMetrics
newtype Metrics = Metrics { appMetricsStore :: IORef AppMetrics}
newMetrics :: IO Metrics
newMetrics =
let
emptyAppMetrics = AppMetrics
{ successCount = 0
, failureCount = 0
, callDuration = Map.empty
}
in Metrics <$> newIORef emptyAppMetrics
tickSuccess :: Metrics → IO ()
tickSuccess (Metrics metricsRef) = modifyIORef metricsRef $ \m →
m { successCount = 1 + successCount m}
tickFailure :: Metrics → IO ()
tickFailure (Metrics metricsRef) = modifyIORef metricsRef $ \m →
m { failureCount = 1 + failureCount m}
timeFunction :: Metrics → String → IO a → IO a
timeFunction (Metrics metrics) actionName action = do
startTime ← getCurrentTime
result ← action
endTime ← getCurrentTime
modifyIORef metrics $ \oldMetrics ->
let
oldDurationValue =
fromMaybe 0 $ Map.lookup actionName (callDuration oldMetrics)
runDuration =
floor . nominalDiffTimeToSeconds $
diffUTCTime endTime startTime
newDurationValue = oldDurationValue + runDuration
in oldMetrics {
callDuration =
Map.insert actionName newDurationValue $
callDuration oldMetrics}
pure result
Code does not compile, throws this error:
The function ‘oldMetrics
{callDuration = Map.insert actionName newDurationValue
$ callDuration oldMetrics}’
is applied to two value arguments,
but its type ‘AppMetrics’ has none
Not able to figure out the problem.