UArray for newtypes (LogFloat)

Felipe Lessa felipe.lessa at gmail.com
Sat Mar 7 08:22:04 EST 2009


Hello,

So, I would like to make an UArray of LogFloat. They are a newtype of
Double, but the type system can't see trough newtypes. So I wonder if
it is acceptable to exploit the fact that the internal representation
of newtypes don't change to use some safe unsafeCoerces and create an
instance of IArray for UArray of LogFloat.

I've looked at the core of the code below and it seems sane, and -Wall
only warn about the orphan instance, so I would also like to ask to
include this instance in logfloat package itself (I've sent a copy of
this message to LogFloat's maintainer).



{-# LANGUAGE MultiParamTypeClasses #-}

import Data.Array.Base
import Data.Array.Unboxed (UArray)
import Data.Number.LogFloat
import Unsafe.Coerce

-- For testing below
import Data.Array.Unboxed as U
import Test.QuickCheck



{-# INLINE from #-}
from :: UArray a LogFloat -> UArray a Double
from = unsafeCoerce
{-# INLINE to #-}
to   :: UArray a Double -> UArray a LogFloat
to   = unsafeCoerce
{-# INLINE func #-}
func :: (LogFloat -> a -> LogFloat) -> (Double -> a -> Double)
func = unsafeCoerce

instance IArray UArray LogFloat where
    {-# INLINE bounds #-}
    bounds =
        bounds .
        from
    {-# INLINE numElements #-}
    numElements =
        numElements .
        from
    {-# INLINE unsafeArray #-}
    unsafeArray lu =
        to .
        unsafeArray lu .
        unsafeCoerce
    {-# INLINE unsafeAt #-}
    unsafeAt =
        unsafeCoerce .
        unsafeAt .
        from
    {-# INLINE unsafeReplace #-}
    unsafeReplace arr =
        to .
        unsafeReplace (from arr) .
        unsafeCoerce
    {-# INLINE unsafeAccum #-}
    unsafeAccum f arr =
        to .
        unsafeAccum (func f) (from arr)
    {-# INLINE unsafeAccumArray #-}
    unsafeAccumArray f initialValue lu =
        to .
        unsafeAccumArray (func f) (unsafeCoerce initialValue) lu





test1 :: [Double] -> Bool
test1 elms' = elms == U.elems arr
    where
      arr  :: UArray Int LogFloat
      arr  = U.listArray (1, length elms) elms
      elms = map (logFloat . abs) elms'

test2 :: [Double] -> Bool
test2 elms' = product elms == arr U.! 1
    where
      arr  :: UArray Int LogFloat
      arr  = U.accumArray (*) 1 (1, 1) [(1,x) | x <- elms]
      elms = map (logFloat . abs) elms'

main :: IO ()
main = quickCheck test1 >> quickCheck test2


-- 
Felipe.


More information about the Libraries mailing list