
Adding 'unsafePerformIO' will work, but a better idea might be to understand why your solver has IO in its type signature. Is this because of FFI calls? You can remove IO in FFI calls if they are free from side effects as well.
My solver has IO in the type signature, because I said so. :o) The solve function is defined like this:
solve :: Constraints -> IOMayfail Solution solve constraints = do { solString <- scip (genZimpl constraints); parseSol nfnrs solString;}
scip :: String -> IOMayfail String scip zimplCode = do {lift $ writeFileAtomic zplFile zimplCode; exitCode <- lift $ system (command zplFile solFile); case exitCode of ExitSuccess -> lift (readFile solFile) ExitFailure n -> fail ("Calling Scip failed with code "++ show n ++".\n");}
command inFile outFile = "./scip -c 'read \"" ++ inFile ++"\"' -c 'optimize' " ++"-c 'write solution \""++outFile++"\"' -c 'quit'"
(I added {}; because I some mail clients use variable width fonts and mess up layout. Eg mine does.) The solver SCIP also offers a FFI interface. But I was too lazy to use that, yet. So I use a temp-file (which should really use openTempFile instead of a fixed name) for communication. So because of my lazyness there are still things in it that look like side-effects, but they are not so in principal. (Also I am the only user of my code, so I can get away with deferring true FFI.) Matthias.