Search code examples
haskellmonad-transformersterminfo

How to use Terminfo's Capability type correctly. Are monad transformers the answer?


I've been struggling to simplify a small program using System.Console.Terminfo. I've gotten as far as mappending multiple Capability together, but whenever I need to evaluate them, I have to use getCapability and then use a case to pattern-match the resulting Maybe. The pattern is always the same

Just ... -> runTermOutput ...
Nothing -> return ()

so I think there must be a better way to do this. It seems to me that the pattern-matching is replacing Maybe with IO, so I thought it might be what monad transformers are for. Looking at the Capability definition,

> :i Capability
newtype Capability a
  = System.Console.Terminfo.Base.Capability (Terminal
                                             -> IO (Maybe a))
...

it does look similar to the MaybeT example I found here on StackOverflow, but the fact that it's a function throws me off. (Plus, I can't claim to understand monad transformers after reading just one example.)

Am I on the right track? Is there a different pattern that can help me avoid writing this case over and over again?

Here's getCapability type:

> :i getCapability 
getCapability :: Terminal -> Capability a -> Maybe a
...

Solution

  • From what I understand, the Terminfo Capability interface means that monad transformers are not the answer.

    As user2407038 suggested, the case pattern can be avoided with the function,

    \t -> maybe (return ()) (runTermOutput t) . (getCapability t)
      :: Terminal -> Capability TermOutput -> IO ()