type PromptSegment = IO (Maybe String)
instance Monoid a => Monoid (IO a) where
mempty = return mempty
mappend = liftA2 (<>)
Questo si comporta esattamente come voglio per i miei scopi.
Ad esempio:
ghci> let a = return $ Just "hello" :: IO Maybe String
ghci> let b = return $ Just " world" :: IO Maybe String
ghci> let c = return $ Nothing :: IO Maybe String
ghci> a 'mappend' b 'mappend' c
Just "hello world"
Tuttavia, sono abbastanza consapevole che forse, per un Monoid diverso a = > Monoid (IO a) istanza diversa da un PromptSegment, forse non vorrei che il mappend si comportasse allo stesso modo ?? Mi sembra che ci sia un modo migliore per farlo rispetto alla creazione dell'istanza monoid orfana sopra.
Design dell'API corrente
currentDirectory :: PromptSegment
currentDirectory = Just <$> getCurrentDirectory
main :: IO ()
main = buildMainPrompt
[ bold . fgColor skyBlue <$> currentDirectory
, (fgColor deepSkyBlue3 . underline . bold <$> gitCurrentBranch)
<> (fgColor defaultDarkGreen . bold <$> gitRepositorySymbol "±")
<> gitStatusSegment
]
(fgColor red0 . bold <$> makePromptSegment " ➢ ")
(fgColor slateBlue0 . bold <$> makePromptSegment " λ» ")
gitStatusSegment :: PromptSegment
gitStatusSegment =
let unstagedSymbol = fgColor gold1 <$> gitUnstagedSymbol "✚"
stagedSymbol = fgColor orange <$> gitStagedSymbol "✎"
pushSymbol = fgColor red1 . bold <$> gitPushSymbol "↑"
in prependSpace <$> unstagedSymbol <> stagedSymbol <> pushSymbol
Questo è, naturalmente, un work in progress, ma lo scopo del programma è creare un DSL per definire i temi del prompt dei cli (a partire da ZSH). Questo ultimo esempio di codice serve principalmente a fornire il contesto la domanda per il motivo per cui vorrei rendere IO (Maybe String) un Monoid. Sono spalancato alle aspre critiche, soprattutto perché questo è il mio primo tentativo di scrivere un programma "reale" in Haskell.