 type MaybeIOVector a = IO (Maybe (Vector a))
 
 readBandBlock :: (Storable a, Typeable a)
-  => Band -> Int -> Int -> MaybeIOVector a
-readBandBlock b x y = do
-  block <- readBandBlock' b x y
+  => Band b -> Int -> Int -> MaybeIOVector a
+readBandBlock b x y =
   liftM (maybe Nothing (\(Block a) -> cast a)) $ readBandBlock' b x y
 
 
-readBandBlock' :: Band -> Int -> Int -> IO (Maybe Block)
+readBandBlock' :: Band b -> Int -> Int -> IO (Maybe Block)
 readBandBlock' b x y = 
   case bandDatatype b of
     GDT_Byte     -> Just . Block <$> (readIt b x y :: IOVector Word8)


data ReadOnly
data ReadWrite
newtype (Dataset a) = Dataset (ForeignPtr (Dataset a), Mutex)

type RODataset = Dataset ReadOnly
type RWDataset = Dataset ReadWrite

        else f rBand

foreign import ccall unsafe "gdal.h GDALGetRasterBand" getRasterBand
        :: (Ptr (Dataset a)) -> (CInt -> (IO ((Band a))))


bandDatatype :: Band a -> Datatype
bandDatatype band = toEnumC . getDatatype_ $ band

foreign import ccall unsafe "gdal.h GDALGetRasterDataType" getDatatype_
   :: Band a -> CInt


bandBlockSize :: Band a -> (Int,Int)
bandBlockSize band = unsafePerformIO $ alloca $ \xPtr -> alloca $ \yPtr -> do
   -- unsafePerformIO is safe here since the block size cant change once
   -- a dataset is created
   getBlockSize_ band xPtr yPtr
   liftA2 (,) (liftM fromIntegral $ peek xPtr) (liftM fromIntegral $ peek yPtr)

foreign import ccall unsafe "gdal.h GDALGetBlockSize" getBlockSize_
    :: Band a -> Ptr CInt -> Ptr CInt -> IO ()


bandBlockLen :: Band a -> Int
bandBlockLen = uncurry (*) . bandBlockSize

bandSize :: Band a -> (Int, Int)
bandSize band
  = (fromIntegral . getXSize_ $ band, fromIntegral . getYSize_ $ band)

foreign import ccall unsafe "gdal.h GDALGetRasterBandXSize" getXSize_
  :: Band a -> CInt

foreign import ccall unsafe "gdal.h GDALGetRasterBandYSize" getYSize_
  :: Band a -> CInt


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

setBandNodataValue :: RWBand -> Double -> IO ()
setBandNodataValue b v = throwIfError "could not set nodata" $
                            setNodata_ b (realToFrac v)

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


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

foreign import ccall safe "gdal.h GDALFillRaster" fillRaster_
    :: RWBand -> CDouble -> CDouble -> IO CInt


class HasDatatype a where
    datatype :: a -> Datatype
