Skip to content

Instantly share code, notes, and snippets.

@ifesdjeen
Last active February 11, 2018 13:05
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ifesdjeen/4be994aea5846aa1c2fe to your computer and use it in GitHub Desktop.
Save ifesdjeen/4be994aea5846aa1c2fe to your computer and use it in GitHub Desktop.
I've got that piece of code that looks extremely overcomplicated to me. Even though every operation by itself is simple, the "sum" of operations is simply insane.
data Query = Query
data SomeObj = SomeObj
data IoOnlyObj = IoOnlyObj
data Err = Err
-- There's a decoder function that makes some object from String
decodeFn :: String -> Either Err SomeObj
decodeFn = undefined
-- There's a query, that runs against DB and returns array of strings
fetchFn :: Query -> IO [String]
fetchFn = undefined
-- there's some additional "context initializer", that also has IO
-- side-effects
makeIoOnlyObj :: [SomeObj] -> IO [(SomeObj, IoOnlyObj)]
makeIoOnlyObj = undefined
-- and now, there's a pipeline function, that takes query,
-- decodes results, and then runs another IO operation with the
-- results of query. And it seems to me that there are much much
-- better ways of implementing such things.
--
-- `makeIoOnlyObj` returns IO-wrapped result, and we need
-- return IO Either-wrapped.
--
-- So far what I've got is as follows. How do I improve it?
pipelineFn :: Query
-> IO (Either Err [(SomeObj, IoOnlyObj)])
pipelineFn query = do
a <- fetchFn query
case sequence (map decodeFn a) of
(Left err) -> return $ Left $ err
(Right res) -> do
a <- makeIoOnlyObj res
return $ Right a
@ifesdjeen
Copy link
Author

Another variation of traverse version, suggested by @bitemyapp is:

pipelineFn :: Query
              -> IO (Either Err [(SomeObj, IoOnlyObj)])
pipelineFn query = do
  a <- fetchFn query
  traverse makeIoOnlyObj (mapM decodeFn a)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment