CDouble type coercion

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

CDouble type coercion

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.

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)


Reply | Threaded
Open this post in threaded view
|

Re: CDouble type coercion

Sven Panne
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.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: CDouble type coercion

SevenThunders
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.
Reply | Threaded
Open this post in threaded view
|

Re: CDouble type coercion

Bugzilla from robdockins@fastmail.fm
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
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: CDouble type coercion

SevenThunders
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.
Reply | Threaded
Open this post in threaded view
|

Re: CDouble type coercion

Twan van Laarhoven
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
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe