
On 4/12/2017 10:59 AM, Saurabh Nanda wrote:
OPTION 1: Use unsafePerformIO to avoid making an otherwise pure function, "impure", i.e.
parseName :: HStore -> FullName -- uses unsafePerformIO to log soft-errors
OPTION 2: Put the data transformation function in IO or the app-wide monad AppM because it will call the logging function, i.e.
parseName :: HStore -> AppM FullName
OPTION 3: Use a wrapper over Writer monad, called ErrorCollector, that forces the calling function to log while accessing the underlying value, i.e.
parseName :: HStore -> ErrorCollector FullName logErrorAndExtract extraLoggingContext (parseName hstoreVal)
May I suggest a fourth option: Keep the utility functions such as parsing pure, and do the logging in the IO threads that are calling them. This is a nice way to keep from polluting general-purpose functions with I/O, whether unsafe or not. If the calling thread doesn't have enough information to produce a meaningful log message, the pure function could return it as part of a Left.