From b782cc34f76fa295026b7e6d5c14930769ba5773 Mon Sep 17 00:00:00 2001
From: "J. Konrad Tegtmeier-Rottach" <jktr@0x16.de>
Date: Wed, 3 May 2023 00:12:37 +0200
Subject: [PATCH] Add type signatures where ghc complains about them

---
 qbar/src/QBar/BlockHelper.hs           |  4 +++-
 qbar/src/QBar/Blocks/Date.hs           |  2 +-
 qbar/src/QBar/Blocks/NetworkManager.hs |  7 ++++++-
 qbar/src/QBar/Blocks/Qubes.hs          | 23 +++++++++++++++++++----
 qbar/src/QBar/Blocks/Script.hs         | 11 +++++++++--
 qbar/src/QBar/Color.hs                 | 11 +++++++----
 qbar/src/QBar/Host.hs                  |  9 ++++++---
 qbar/src/QBar/Qubes/AdminAPI.hs        | 12 +++++++++++-
 qbar/src/QBar/Server.hs                | 11 ++++++++++-
 qbar/src/QBar/Theme.hs                 |  4 +---
 qbar/src/QBar/Time.hs                  |  2 +-
 11 files changed, 74 insertions(+), 22 deletions(-)

diff --git a/qbar/src/QBar/BlockHelper.hs b/qbar/src/QBar/BlockHelper.hs
index 6366bf8..8d51274 100644
--- a/qbar/src/QBar/BlockHelper.hs
+++ b/qbar/src/QBar/BlockHelper.hs
@@ -195,7 +195,9 @@ runSignalBlockConfiguration SignalBlockConfiguration{aquire, release, signalThre
             sendSignal signal = do
               maybeOutput <- request signal
 
-              let updateInvalidatedState = if isEventSignal signal then (_2 .~ False) else id
+              let
+                updateInvalidatedState :: (Maybe BlockUpdate, Bool) -> (Maybe BlockUpdate, Bool)
+                updateInvalidatedState = if isEventSignal signal then _2 .~ False else id
 
               let blockUpdate = (mkBlockStateWithHandler maybeOutput, signalToReason signal)
               liftIO . atomically $ modifyTVar renderStateVar ((_1 . _Just .~ blockUpdate) . updateInvalidatedState)
diff --git a/qbar/src/QBar/Blocks/Date.hs b/qbar/src/QBar/Blocks/Date.hs
index 9194dac..dcafa7e 100644
--- a/qbar/src/QBar/Blocks/Date.hs
+++ b/qbar/src/QBar/Blocks/Date.hs
@@ -16,7 +16,7 @@ import Data.Time.LocalTime
 dateBlock :: Block
 dateBlock = runPollBlock' (everyNSeconds 60) $ forever $ do
   zonedTime <- liftIO getZonedTime
-  let logo = "📅\xFE0E "
+  let logo :: Text = "📅\xFE0E "
   let date = T.pack (formatTime defaultTimeLocale "%a %F" zonedTime)
   let time = T.pack (formatTime defaultTimeLocale "%R" zonedTime)
   let text = normalText (logo <> date <> " ") <> activeText time
diff --git a/qbar/src/QBar/Blocks/NetworkManager.hs b/qbar/src/QBar/Blocks/NetworkManager.hs
index 6c84053..6aa7c15 100644
--- a/qbar/src/QBar/Blocks/NetworkManager.hs
+++ b/qbar/src/QBar/Blocks/NetworkManager.hs
@@ -74,8 +74,13 @@ networkManagerBlock = runSignalBlockConfiguration $ SignalBlockConfiguration {
       return client
     release :: DBus.Client -> BarIO ()
     release = liftIO . DBus.disconnect
+
     networkManagerBlock' :: DBus.Client -> SignalBlock ()
-    networkManagerBlock' client = (liftBarIO . networkManagerBlock'' client) >=> respondBlockUpdate >=> networkManagerBlock' client
+    networkManagerBlock' client
+      = (liftBarIO . networkManagerBlock'' client)
+      >=> (\x -> respondBlockUpdate x) -- why doesn't this type check without \->?
+      >=> networkManagerBlock' client
+
     networkManagerBlock'' :: DBus.Client -> Signal () -> BarIO BlockOutput
     networkManagerBlock'' client _ = do
       primaryConnection <- runExceptT_ $ getPrimaryConnectionPath client
diff --git a/qbar/src/QBar/Blocks/Qubes.hs b/qbar/src/QBar/Blocks/Qubes.hs
index f0e0ede..14dd6d4 100644
--- a/qbar/src/QBar/Blocks/Qubes.hs
+++ b/qbar/src/QBar/Blocks/Qubes.hs
@@ -30,12 +30,17 @@ diskUsageQubesBlock = runPollBlock $ forever $ do
     action = liftIO qubesUsageOfDefaultPool >>= \case
       (Just usage, Just size) -> return $ createBlockOutput $ size - usage
       _ -> return $ mkErrorOutput "unknown"
+
     createBlockOutput :: Int -> BlockOutput
     createBlockOutput free =
       mkBlockOutput $ chooseColor free $ formatSize free
+
+    chooseColor :: Int -> Text -> BlockText
     chooseColor free = if free < 40 * 1024*1024*1024
       then activeText
       else normalText
+
+    sizeUnits :: [(Text, Int)]
     sizeUnits = [
         ("T", 1024*1024*1024*1024),
         ("G", 1024*1024*1024),
@@ -52,8 +57,10 @@ pipeBlockWithEvents prod block = runSignalBlock Nothing (Just produce) sblock
   where
     produce :: (a -> IO ()) -> BarIO ()
     produce yield' = runEffect $ prod >-> forever (await >>= liftIO . yield')
+
     sblock :: Signal a -> P.Server (Signal a) (Maybe BlockOutput) BarIO ExitBlock
     sblock = lift . sblock' >=> respond >=> sblock
+
     sblock' :: Signal a -> BarIO (Maybe BlockOutput)
     sblock' RegularSignal = return Nothing  -- ignore timer
     sblock' (UserSignal x) = block $ Right x
@@ -62,12 +69,20 @@ pipeBlockWithEvents prod block = runSignalBlock Nothing (Just produce) sblock
 qubesMonitorPropertyBlock :: BL.ByteString -> Block
 qubesMonitorPropertyBlock name = pipeBlockWithEvents (qubesMonitorProperty qubesEvents name) handle
   where
+    handle :: Either a QubesPropertyInfo -> BarIO (Maybe BlockOutput)
     handle = fmap handle' . either (const $ liftIO $ qubesGetProperty name) return
+
     handle' QubesPropertyInfo {propValue, propIsDefault} = Just $ mkBlockOutput $ normalText $ decode propValue <> (if propIsDefault then " (D)" else "")
     decode = decodeUtf8With lenientDecode
 
 qubesVMCountBlock :: Block
-qubesVMCountBlock = pipeBlockWithEvents qubesListVMsP $ fmap countVMs . either (const $ liftIO $ qubesListVMs) return where
-  countVMs = Just . format . M.size . M.filterWithKey isRunningVM
-  isRunningVM name x = vmState x == VMRunning && name /= "dom0"
-  format n = mkBlockOutput $ normalText $ T.pack (show n) <> " Qube" <> (if n /= 1 then "s" else "")
+qubesVMCountBlock = pipeBlockWithEvents qubesListVMsP $ fmap countVMs . either (const $ liftIO qubesListVMs) return
+  where
+    countVMs :: M.Map BL.ByteString  QubesVMInfo -> Maybe BlockOutput
+    countVMs = Just . format . M.size . M.filterWithKey isRunningVM
+
+    isRunningVM :: BL.ByteString -> QubesVMInfo -> Bool
+    isRunningVM name x = vmState x == VMRunning && name /= "dom0"
+
+    format :: Int -> BlockOutput
+    format n = mkBlockOutput $ normalText $ T.pack (show n) <> " Qube" <> (if n /= 1 then "s" else "")
diff --git a/qbar/src/QBar/Blocks/Script.hs b/qbar/src/QBar/Blocks/Script.hs
index 352a964..37b799e 100644
--- a/qbar/src/QBar/Blocks/Script.hs
+++ b/qbar/src/QBar/Blocks/Script.hs
@@ -28,7 +28,11 @@ import System.Process.Typed (Process, shell, setStdin, setStdout,
 
 
 pollScriptBlock :: Interval -> FilePath -> Block
-pollScriptBlock interval path = runPollBlock' interval $ forever $ yieldBlockUpdate =<< (lift blockScriptAction)
+pollScriptBlock interval path = runPollBlock' interval $ forever $ do
+  -- Why doesn't this typecheck when using >>= instead?
+  x <- lift blockScriptAction
+  yieldBlockUpdate x
+
   where
     blockScriptAction :: BarIO BlockOutput
     blockScriptAction = do
@@ -58,6 +62,7 @@ scriptBlock clickEvents path = startScriptProcess
         startScriptProcess
       Right x  -> x
       where
+        result :: Either Text Block
         result = case (isEOFError exc, exitCode) of
           (True, Just ExitSuccess)      -> Right exitBlock
           (True, Just (ExitFailure nr)) ->
@@ -92,7 +97,9 @@ scriptBlock clickEvents path = startScriptProcess
         else startScriptProcessNoEvents
     startScriptProcessNoEvents :: Block
     startScriptProcessNoEvents = do
-      let processConfig = setStdin closed $ setStdout createPipe $ shell path
+      let
+        processConfig :: ProcessConfig () Handle ()
+        processConfig = setStdin closed $ setStdout createPipe $ shell path
       process <- startProcess processConfig
       -- The inner catchP catches errors that happen after the process has been created
       -- This handler will also make sure the process is stopped
diff --git a/qbar/src/QBar/Color.hs b/qbar/src/QBar/Color.hs
index be259fe..fa45c54 100644
--- a/qbar/src/QBar/Color.hs
+++ b/qbar/src/QBar/Color.hs
@@ -16,8 +16,11 @@ import Numeric (showHex)
 
 data Color = ColorRGB (RGB Double) | ColorRGBA (RGB Double) Double
   deriving (Eq, Show)
+
 instance FromJSON Color where
-  parseJSON = withText "Color" $ either fail pure . parseOnly (colorParser <* endOfInput)
+  parseJSON :: Value -> AT.Parser Color
+  parseJSON = withText "Color" $ either fail pure . A.parseOnly (colorParser <* endOfInput) . T.fromStrict
+
 instance ToJSON Color where
   toJSON = String . T.toStrict . hexColorText
 
@@ -39,17 +42,17 @@ hexColorText = hexColor'
     paddedHexComponent :: Text -> Text
     paddedHexComponent hex =
       let len = 2 - T.length hex
-          padding = if len == 1 then "0" else ""
+          padding :: Text = if len == 1 then "0" else ""
       in padding <> hex
 
 
-colorParser :: Parser Color
+colorParser :: A.Parser Color
 colorParser = do
   void $ char '#'
   rgb <- RGB <$> doubleFromHex2 <*> doubleFromHex2 <*> doubleFromHex2
   option (ColorRGB rgb) (ColorRGBA rgb <$> doubleFromHex2)
   where
-    doubleFromHex2 :: Parser Double
+    doubleFromHex2 :: A.Parser Double
     doubleFromHex2 = (/ 256) . fromIntegral <$> hexadecimal'' 2
 
     -- Variant of 'Data.Attoparsec.Text.hexadecimal' that parses a fixed amount of digits.
diff --git a/qbar/src/QBar/Host.hs b/qbar/src/QBar/Host.hs
index 50e2aee..75f01fd 100644
--- a/qbar/src/QBar/Host.hs
+++ b/qbar/src/QBar/Host.hs
@@ -240,11 +240,14 @@ runBarHost' initializeBarAction = do
     attachBarOutputImpl :: MVar ExitCode -> Producer [BlockOutput] IO () -> Consumer BlockEvent IO () -> (Consumer [BlockOutput] IO (), Producer BlockEvent IO ()) -> IO ()
     attachBarOutputImpl exitMVar blockOutputProducer eventConsumer (barOutputConsumer, barEventProducer) = do
 
-
-      let handleBarEventInput = liftIO $ runEffect $ barEventProducer >-> eventConsumer
+      let
+        handleBarEventInput :: IO ()
+        handleBarEventInput = liftIO $ runEffect $ barEventProducer >-> eventConsumer
       liftIO $ void $ forkFinally handleBarEventInput $ handleOnExitCodeException (\result -> hPutStrLn stderr $ "An event input handler failed: " <> show result)
 
-      let handleBarOutput = liftIO $ runEffect $ blockOutputProducer >-> filterDuplicates >-> barOutputConsumer
+      let
+        handleBarOutput :: IO ()
+        handleBarOutput = liftIO $ runEffect $ blockOutputProducer >-> filterDuplicates >-> barOutputConsumer
       liftIO $ void $ forkFinally handleBarOutput $ handleOnExitCodeException (\result -> hPutStrLn stderr $ "A bar output handler failed: " <> show result)
 
       where
diff --git a/qbar/src/QBar/Qubes/AdminAPI.hs b/qbar/src/QBar/Qubes/AdminAPI.hs
index 73a7146..649779d 100644
--- a/qbar/src/QBar/Qubes/AdminAPI.hs
+++ b/qbar/src/QBar/Qubes/AdminAPI.hs
@@ -79,6 +79,8 @@ instance Binary QubesAdminReturn where
     where
       getPairs = untilZeroByte $ (,) <$> getLazyByteStringNul <*> getLazyByteStringNul
       getFields = untilZeroByte getLazyByteStringNul
+
+      untilZeroByte :: Get a -> Get [a]
       untilZeroByte inner = lookAhead getWord8 >>= \case
         0x00 -> getWord8 >> return []
         _    -> inner >>= \x -> (x:) <$> untilZeroByte inner
@@ -110,6 +112,7 @@ qubesTryAdminCall serviceName args = do
 
 qubesAdminCall :: BL.ByteString -> [BL.ByteString] -> IO BL.ByteString
 qubesAdminCall serviceName args = qubesTryAdminCall serviceName args >>= extract where
+  extract :: QubesAdminReturn -> IO BLC.ByteString
   extract Ok {okContent} = return okContent
   extract x@Exception {} = fail $ "service has returned an exception: " <> show x
   extract Event {} = fail "service has returned events instead of a reply"
@@ -164,7 +167,9 @@ qubesVMStats = qubesVMStatsRaw >-> P.mapFoldable parse where
     | otherwise = Nothing  -- shouldn't happen -> report error?
   parse _ = Nothing  -- shouldn't happen -> report error?
 
-  absent = (-1)
+  absent :: Int = -1
+
+  readBL :: BLC.ByteString -> Int
   readBL = read . BLC.unpack
 
   addProperties :: [(BL.ByteString, BL.ByteString)] -> QubesVMStats -> QubesVMStats
@@ -313,6 +318,7 @@ qubesGetPoolInfo name = map parseLine <$> qubesAdminCallLines "admin.pool.Info"
 qubesUsageOfDefaultPool :: IO (Maybe Int, Maybe Int)
 qubesUsageOfDefaultPool = qubesGetDefaultPool >>= qubesGetPoolInfo >>= extract
   where
+    extract :: [(BLC.ByteString, BLC.ByteString)] -> IO (Maybe Int, Maybe Int)
     extract props = return (tryReadProp "usage" props, tryReadProp "size" props)
     tryReadProp :: Read a => BL.ByteString -> [(BL.ByteString, BL.ByteString)] -> Maybe a
     tryReadProp name props = readMaybe . BLC.unpack =<< lookup name props
@@ -348,7 +354,10 @@ qubesMonitorProperty :: forall m. MonadIO m
   => Producer QubesEvent m () -> BL.ByteString -> Producer QubesPropertyInfo m ()
 qubesMonitorProperty events name = events >-> P.filter isRelevant >-> fetchValue
   where
+    fetchValue :: Proxy () QubesEvent () QubesPropertyInfo m b
     fetchValue = liftIO (qubesGetProperty name) >>= go
+
+    go :: QubesPropertyInfo -> Proxy () QubesEvent () QubesPropertyInfo m b
     go x = do
       yield x
       ev <- await
@@ -356,6 +365,7 @@ qubesMonitorProperty events name = events >-> P.filter isRelevant >-> fetchValue
         PropertySet {newValue} -> go $ x { propIsDefault = False, propValue = newValue }
         PropertyDel {} -> fetchValue
         _ -> go x
+
     isRelevant PropertySet {changedProperty} = name == changedProperty
     isRelevant PropertyDel {changedProperty} = name == changedProperty
     isRelevant _ = False
diff --git a/qbar/src/QBar/Server.hs b/qbar/src/QBar/Server.hs
index 3737c9c..bd18213 100644
--- a/qbar/src/QBar/Server.hs
+++ b/qbar/src/QBar/Server.hs
@@ -44,9 +44,16 @@ instance ToJSON PangoBlock where
   toJSON PangoBlock{pangoBlockFullText, pangoBlockShortText, pangoBlockName} = object $
     fullText' <> shortText' <> blockName' <> pango'
     where
+      fullText' :: [AT.Pair]
       fullText' = [ "full_text" .= pangoBlockFullText ]
+
+      shortText' :: [AT.Pair]
       shortText' = fromMaybe (\s -> ["short_text" .= s]) mempty pangoBlockShortText
+
+      blockName' :: [AT.Pair]
       blockName' = fromMaybe (\s -> ["name" .= s]) mempty pangoBlockName
+
+      pango' :: [AT.Pair]
       pango' = [ "markup" .= ("pango" :: T.Text) ]
 
 
@@ -64,7 +71,9 @@ swayBarInput MainOptions{verbose} = swayBarInput'
           liftIO $ BSSC8.hPutStrLn stderr line
           hFlush stderr
 
-        let maybeBlockEvent = decode $ removeComma $ BS.fromStrict line
+        let
+          maybeBlockEvent :: Maybe BlockEvent
+          maybeBlockEvent = decode $ removeComma $ BS.fromStrict line
         forM_ maybeBlockEvent yield
 
       swayBarInput'
diff --git a/qbar/src/QBar/Theme.hs b/qbar/src/QBar/Theme.hs
index 3c92f85..d1c20a9 100644
--- a/qbar/src/QBar/Theme.hs
+++ b/qbar/src/QBar/Theme.hs
@@ -50,7 +50,6 @@ data ThemedBlockTextSegment = ThemedBlockTextSegment {
   }
   deriving (Eq, Show)
 
-
 data Theme = StaticTheme StaticTheme | AnimatedTheme AnimatedTheme
 
 type StaticTheme = [BlockOutput] -> [ThemedBlockOutput]
@@ -78,6 +77,7 @@ themes = HM.fromList themesList
 findTheme :: Text -> Either Text Theme
 findTheme themeName = maybe invalidThemeName Right $ HM.lookup themeName themes
   where
+    invalidThemeName :: Either Text Theme
     invalidThemeName = Left $ "Invalid theme: " <> themeName
 
 mkTheme :: SimplifiedTheme -> Theme
@@ -122,7 +122,6 @@ mkThemedSegment (color, backgroundColor) text = ThemedBlockTextSegment{themedSeg
 whiteThemedBlockOutput :: Text -> ThemedBlockOutput
 whiteThemedBlockOutput = mkThemedBlockOutput (ColorRGB (RGB 1 1 1), Nothing)
 
-
 invalidColor :: Color
 invalidColor = ColorRGBA (RGB (0x96 / 255) (0x98 / 255) (0x96 / 255)) (0x77 / 255)
 
@@ -142,7 +141,6 @@ defaultTheme = mkTheme defaultTheme'
     defaultTheme' True (NormalImportant _) = (ColorRGB (RGB 1 1 1), Nothing)
     defaultTheme' False (NormalImportant _) = (ColorRGB (RGB (0x96 / 255) (0x98 / 255) (0x96 / 255)), Nothing)
 
-
 rainbowTheme :: Theme
 rainbowTheme = AnimatedTheme rainbowThemePipe
   where
diff --git a/qbar/src/QBar/Time.hs b/qbar/src/QBar/Time.hs
index 15a2121..af315a2 100644
--- a/qbar/src/QBar/Time.hs
+++ b/qbar/src/QBar/Time.hs
@@ -39,7 +39,7 @@ nextIntervalTime :: MonadIO m => Interval -> m UTCTime
 nextIntervalTime (IntervalSeconds intervalSeconds) = liftIO $ do
   now <- getCurrentTime
   let dayTime = utctDayTime now
-  let daySeconds = floor dayTime
+  let daySeconds :: Integer = floor dayTime
   let intervalId = daySeconds `div` intervalSeconds
   return now {
     utctDayTime = fromInteger $ (intervalId + 1) * intervalSeconds
-- 
GitLab