
I am new to Haskell and found myself in a bind concerning the use of the C types, CDouble in particular. I extract a CDouble via it's pointer from a StorableArray. Since the array must interface with C the elements of the array must be CDouble. Now I'd like to use Text.Printf to format print statements of elements of the array, but Text.Printf requires Doubles as inputs and so far I have not found an obvious way to coerce CDoubles into Doubles. Additionally, withStorableArray returns a monad containing a CDouble instead of Double as peek I suppose does. Because I cant coerce my CDouble into a Double, printf chokes. Thus the following code fails to compile on GHC import Foreign import Foreign.C import Foreign.C.Types (CInt, CDouble ) import Data.Array.Storable import Text.Printf foreign import ccall "matrix_c.h sumarr" sumarr :: Ptr CDouble -> IO (CDouble) main = do arr <- newListArray (1 , 3) [3,2,1]:: IO (StorableArray Int CDouble) -- extract the pointer to arr withStorableArray arr sumarr >>= (\x -> printf "15.7f\n" x) The error message is, test2.hs:13:44: No instance for (PrintfArg CDouble) arising from use of `printf' at test2.hs:13:44-49 Probable fix: add an instance declaration for (PrintfArg CDouble) In a lambda abstraction: \ x -> printf "15.7f\n" x In the second argument of `(>>=)', namely `(\ x -> printf "15.7f\n" x)' In the result of a 'do' expression: (withStorableArray arr sumarr) >>= (\ x -> printf "15.7f\n" x) -- View this message in context: http://www.nabble.com/CDouble-type-coercion-t1615450.html#a4378492 Sent from the Haskell - Haskell-Cafe forum at Nabble.com.

Am Sonntag, 14. Mai 2006 09:30 schrieb SevenThunders:
I am new to Haskell and found myself in a bind concerning the use of the C types, CDouble in particular. I extract a CDouble via it's pointer from a StorableArray. Since the array must interface with C the elements of the array must be CDouble. Now I'd like to use Text.Printf to format print statements of elements of the array, but Text.Printf requires Doubles as inputs and so far I have not found an obvious way to coerce CDoubles into Doubles. [...]
You can use the Prelude function realToFrac to convert between the various floating-point types: ---------------------------------------------------------------- panne@jeanluc:~> ghci -v0 Prelude> :t realToFrac realToFrac :: (Fractional t1, Real t) => t -> t1 Prelude> (realToFrac :: Foreign.C.Types.CDouble -> Double) 1234.5 1234.5 ---------------------------------------------------------------- As you can see from its type, realToFrac is not exactly about floating-point conversions, but for almost all practical use cases it is. :-) Cheers, S.

Thanks that helps a bit. The realToFrac type coercion works, but ultimately it seems that printf won't play nice. Consider this simple haskell code module Test where import IO -- import Data.Array.Storable import Text.Printf import Foreign.C.Types (CInt, CDouble ) y :: CDouble y = 5.2 u = realToFrac(y) test = do printf "%14.7g" u Compiling it into GHCi I get the error, test.hs:13:11: No instance for (PrintfType (t t1)) arising from use of `printf' at test.hs:13:11-16 Probable fix: add an instance declaration for (PrintfType (t t1)) In the result of a 'do' expression: printf "%14.7g" u In the definition of `test': test = do printf "%14.7g" u Failed, modules loaded: none. If I replace the printf by a standard print there is no problem. Also if I comment out the line with test = ... , it will load (compile) and I can then type in the interpreter printf "%14.7g" u and it works! but printf "%14.7g" y fails because y is of type CDouble. At this point I think I'm giving up on the formatted printing in Haskell. It's just too persnickety. I guess I'll just call printf via C and see what happens. -- View this message in context: http://www.nabble.com/CDouble-type-coercion-t1615450.html#a4383006 Sent from the Haskell - Haskell-Cafe forum at Nabble.com.

On Sunday 14 May 2006 03:00 pm, SevenThunders wrote:
Thanks that helps a bit. The realToFrac type coercion works, but ultimately it seems that printf won't play nice. Consider this simple haskell code
module Test where import IO -- import Data.Array.Storable import Text.Printf import Foreign.C.Types (CInt, CDouble )
y :: CDouble y = 5.2 u = realToFrac(y) test = do printf "%14.7g" u
Try: y :: CDouble y = 5.2 u :: Double u = realToFrac(y) test = do printf "%14.7g" u The root problem seems to be that GHC isn't sure what type 'u' has unless you fix it with a type signature because 'realToFrac' has a polymorphic type. I'm not sure why it works when you type it at the interpreter.
Compiling it into GHCi I get the error, test.hs:13:11: No instance for (PrintfType (t t1)) arising from use of `printf' at test.hs:13:11-16 Probable fix: add an instance declaration for (PrintfType (t t1)) In the result of a 'do' expression: printf "%14.7g" u In the definition of `test': test = do printf "%14.7g" u Failed, modules loaded: none.
If I replace the printf by a standard print there is no problem. Also if I comment out the line with test = ... , it will load (compile) and I can then type in the interpreter printf "%14.7g" u and it works!
but printf "%14.7g" y
fails because y is of type CDouble. At this point I think I'm giving up on the formatted printing in Haskell. It's just too persnickety. I guess I'll just call printf via C and see what happens.
-- View this message in context: http://www.nabble.com/CDouble-type-coercion-t1615450.html#a4383006 Sent from the Haskell - Haskell-Cafe forum at Nabble.com.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

The rabbit hole goes a bit deeper I'm afraid y :: CDouble y = 5.2 u :: Double u = realToFrac(y) test = do printf "%14.7g" u gives Compiling Test ( test.hs, interpreted ) test.hs:14:11: No instance for (PrintfType (t t1)) arising from use of `printf' at test.hs:14:11-16 Probable fix: add an instance declaration for (PrintfType (t t1)) In the result of a 'do' expression: printf "%14.7g" u In the definition of `test': test = do printf "%14.7g" u Failed, modules loaded: none. But in fact just this, gives the same error test = do printf "%14.7g" 3.14 Now in the command line I get errors under various configurations but a few of them work e.g. works
printf "%g" u printf "%g" (3.14 :: Double) do printf "%g" u do printf "%g" (3.14 :: Double)
fails printf "%g" y -- y is a CDouble printf "%g" 3.14 All forms fail when compiled from a .hs file. However, this just in! I finally got something to work, namely this piece of code test = do (printf "%14.7g" (u :: Double)) :: IO() I guess the output of printf has to be disambiguated. There should probably be a few examples of this in the library documentation. This also works, by returning a string... test = printf "%14.7g" (u :: Double) :: String Thanks for the help by the way, without realtoFrac there would be no way for me to use this at all. -- View this message in context: http://www.nabble.com/CDouble-type-coercion-t1615450.html#a4385065 Sent from the Haskell - Haskell-Cafe forum at Nabble.com.

SevenThunders wrote:
test.hs:14:11: No instance for (PrintfType (t t1)) arising from use of `printf' at test.hs:14:11-16 Probable fix: add an instance declaration for (PrintfType (t t1)) In the result of a 'do' expression: printf "%14.7g" u In the definition of `test': test = do printf "%14.7g" u Failed, modules loaded: none.
The problem here appears to be the monomorphism restriction. This means that all declarations without arguments get a monomorphic type, a type without variables. The type of 'test' would be 'PrintfType r => r', but the compiler does not allow this type. The solution is to either: - make the type explicit by adding a type declaration, "test :: IO ()" or "Test :: PrintfType r => r" - make test local in a context where it is only used as an IO action, for example: > main :: IO () > main = do {... ; test ; ...} > where test = printf "%14.7g" 3.14 - add a parameter to test Twan
participants (4)
-
Robert Dockins
-
SevenThunders
-
Sven Panne
-
Twan van Laarhoven