type PromptSegment = IO (Maybe String) instance Monoid a => Monoid (IO a) where mempty = return mempty mappend = liftA2 (<>)
This behaves exactly how I want for my purposes.
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"
However, I'm pretty aware that maybe, for a different Monoid a => Monoid (IO a) instance other than a PromptSegment, maybe I wouldn't want mappend to behave the same way?? I feel like there's better way to do this than creating the orphan monoid instance above.
Current API design
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
This is, of course, a work in progress, but the aim of the program is to create a DSL for defining cli prompt themes (starting with ZSH).This last code sample is mostly to serve the purpose of providing context to the question for why I would want to make IO (Maybe String) a Monoid. I'm wide open to harsh criticism - especially since this is my first attempt at writing a 'real' program in Haskell.