 
 
 bandNodataValue :: (Band s t a) -> GDAL s (Maybe Double)
-bandNodataValue b = liftIO $ alloca $ \p -> do
-   value <- liftM realToFrac $ getNodata_ b p
+bandNodataValue = fmap (fmap realToFrac) . liftIO . c_bandNodataValue
+
+c_bandNodataValue :: (Band s t a) -> IO (Maybe CDouble)
+c_bandNodataValue b = alloca $ \p -> do
+   value <- getNodata_ b p
    hasNodata <- liftM toBool $ peek p
    return (if hasNodata then Just value else Nothing)
+{-# INLINE c_bandNodataValue #-}
    
 foreign import ccall unsafe "gdal.h GDALGetRasterNoDataValue" getNodata_
    :: (Band s t a) -> Ptr CInt -> IO CDouble

foreign import ccall safe "gdal.h GDALSetRasterNoDataValue" setNodata_
    :: (RWBand s t) -> CDouble -> IO CInt

setBandNodataDefault :: forall s a. GDALType a => (RWBand s a) -> GDAL s ()
setBandNodataDefault = flip setBandNodataValue (nodataAsDouble (nodata :: a))


fillBand :: (RWBand s a) -> Double -> Double -> GDAL s ()
fillBand b r i = liftIO $ throwIfError "could not fill band" $
    fillRaster_ b (realToFrac r) (realToFrac i)

    fail _              = NoData

instance Storable a => Storable (Value a) where
  sizeOf _ = sizeOf (undefined :: a) + sizeOf (undefined :: Word8)
  alignment _ = alignment (undefined :: a)

  {-# INLINE peek #-}
  peek p = do
            let p1 = (castPtr p::Ptr Word8) `plusPtr` 1
            t <- peek (castPtr p::Ptr Word8)
            if t/=0
              then fmap Value (peekElemOff (castPtr p1 :: Ptr a) 0)
              else return NoData

  {-# INLINE poke #-}
  poke p x = case x of
    NoData -> poke (castPtr p :: Ptr Word8) 0
    Value a -> do
        poke (castPtr p :: Ptr Word8) 1
        let p1 = (castPtr p :: Ptr Word8) `plusPtr` 1
        pokeElemOff (castPtr p1) 0 a

isNoData :: Value a -> Bool
