avalues, but need to work with type class instances for
List. We can think of these as "levels" of wrappers:
Either, then it's pretty straightforward. To access the inner
Maybe, you need to find a way to get into
Eitherstructure, do what you need at that level, and get back out again. You can have all of your functions wrap and unwrap the various layers, but that composes badly and leads to a lot of boilerplate.
lifta function through the layers. Take something that works on one layer, and make it work on another. We can do this manually, but for all of the common data types, there are type classes to help us do this in a straightforward way. By far the most common one is
IOactions occur frequently. Accessing CLI input, talking to the database, and making a network request are all things that you'll want to do on a regular basis. If the monad that you're working in also has a
MonadIOinstance, you get access to
liftIO. Fission uses
MonadRIOvery frequently, which inherits from
MonadIO. The best way to read
liftIOis as "turn an
IOfunction into one that happens in my current wrapper."
createPool :: IO (Pool SeldaConnection)needs to be brought into
RIO. Remember that
IOdoesn't export a constructor for us to explicitly destructure and repackage! We need a way to turn
RIO cfg a.
RIO. The upshot is that it makes
IOactions compatible with the rest of your