美文网首页
Haskell中Storable的使用

Haskell中Storable的使用

作者: DarkBubble | 来源:发表于2018-06-18 12:46 被阅读12次

    Haskell支持指针和堆内存的分配和使用,主要使用Foreign模块里面的功能。要使用Haskell的指针类型(主要是Ptr a)需要满足(Storable a)。在GHCI中查看class Storable接口的定义:

    Prelude> import Foreign
    Prelude Foreign> :i Storable 
    class Storable a where
      sizeOf :: a -> Int
      alignment :: a -> Int
      peekElemOff :: Ptr a -> Int -> IO a
      pokeElemOff :: Ptr a -> Int -> a -> IO ()
      peekByteOff :: Ptr b -> Int -> IO a
      pokeByteOff :: Ptr b -> Int -> a -> IO ()
      peek :: Ptr a -> IO a
      poke :: Ptr a -> a -> IO ()
      {-# MINIMAL sizeOf,
                  alignment,
                  (peek | peekElemOff | peekByteOff),
                  (poke | pokeElemOff | pokeByteOff) #-}
        -- Defined in ‘Foreign.Storable’
    

    我们假设要实现一个代数数据类型的Storable Instance,参考下面的例子:

      1 import Foreign
      2 
      3 data MyData = MyData Int Double deriving(Eq, Show, Read)
      4 
      5 instance Storable MyData where
      6     sizeOf _ = 16
      7     alignment _ = 8
      8     peek ptr = let ptr_x = castPtr ptr :: Ptr Int
      9                    ptr_y = castPtr (ptr_x `advancePtr` 1) :: Ptr Double
     10                in  do x <- peek ptr_x
     11                       y <- peek ptr_y
     12                       return $ MyData x y
     13     poke ptr d = let ptr_x = castPtr ptr :: Ptr Int
     14                      ptr_y = castPtr (ptr_x `advancePtr` 1) :: Ptr Double
     15                      MyData x y = d
     16                  in  do poke ptr_x x
     17                         poke ptr_y y
    

    对于一个带参类型,实现Storable Instance还需要注意下面的问题:

    1. 自定义ADT中,要求所有被存储在堆内存的成员数据类型也是Storable Instance
    2. 自定义ADT中,sizeOfalignment两个接口尽量使用_来作为输入参数,而不要对ADT数据进行任意部分的求值,否则可能引起malloc接口的错误,因为malloc接口会使用undefined作为构造ADT的参数,一旦求值即会报错
    3. 要实现上述要求必须开启ScopedTypeVariable语法扩展,即作用域类型变量,也就是作为参数类型a可以用于undefined :: a
      例如:
    {-# LANGUAGE ScopedTypeVariable #-}
    
    data Vector a = Vector a a a deriving(Eq, Show, Read)
    
    instance Storable a => Storable (Vector a) where
        sizeOf _ = sizeOf (undefined :: a) * 3 -- Scoped type variable 'a'
        alignment _ = sizeOf (undefined :: a) -- Scoped type variable 'a'
        {- ... -}
    

    相关文章

      网友评论

          本文标题:Haskell中Storable的使用

          本文链接:https://www.haomeiwen.com/subject/qfwieftx.html