'How do I create a Haskell function like error (i.e. String -> a)
In Haskell, the error function has signature String -> a. It can return any type because it never actually returns. (It prints its argument and terminates the program.)
I've written a function in C that does something similar. It logs the string that is passed and terminates the process. Is there a way I can write a Haskell wrapper to have the same signature as error?
The C function has the form void RaiseError(char* msg) { ... }
So far, I have
foreign import capi safe "file.h RaiseError"
c_RaiseError :: CString -> IO ()
raiseError :: String -> a
raiseError msg = unsafePerformIO $ do
withCString msg c_RaiseError -- Does not return
return (error "") -- Never gets called
There must be a more elegant way to do this.
Solution 1:[1]
You can implement a function of type String -> a in pure Haskell, but it won't have the same behavior as error:
error1 :: String -> a
error1 = error1
Calling error1 will loop forever rather than printing the message and exiting.
The function Control.Exception.throw is similar to error in that it throws an exception without needing IO. You could use it to implement your own version of error:
import Control.Exception (ErrorCall(..), throw)
error2 :: String -> a
error2 msg = throw (ErrorCall msg)
Calling error2 will be almost the same as calling error, except it won't have a call stack. (Call stacks are a relatively recent addition to error; see errorWithoutStackTrace.)
Ultimately you can't implement something like error in pure Haskell without relying on something like throw. error itself is implemented in terms of raise#, which is a primop. You can use the FFI, but you'll still have to rely on other primops like unsafePerformIO or unsafeCoerce.
This is the most elegant thing I could come up with:
import Foreign.C.String (CString, withCString)
import System.IO.Unsafe (unsafePerformIO)
import Unsafe.Coerce (unsafeCoerce)
foreign import ccall "file.h RaiseError"
c_RaiseError :: CString -> IO ()
error3 :: String -> a
error3 = unsafeCoerce
. unsafePerformIO
. flip withCString c_RaiseError
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Taylor Fausak |
