2

Storable オブジェクト (異なるタイプ) の異種リストを突くことができる関数を書きたい

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes, ExistentialQuantification, ImpredicativeTypes #-}

pokeMany :: Ptr b -> Int -> [forall a. Storable a => a] -> IO ()
pokeMany _ _ [] = return ()
pokeMany ptr offset (x:xs) = do
    pokeByteOff ptr offset x
    pokeMany ptr (offset + sizeOf x) xs

somePoke :: Ptr a -> Int -> Int -> IO ()
somePoke ptr x1 x2 = pokeMany ptr 0 [x1, x2]

しかし、コンパイルエラーが発生します:

No instance for (Storable a1) arising from a use of `sizeOf'
The type variable `a1' is ambiguous
Note: there are several potential instances:
  instance Storable CChar -- Defined in `Foreign.C.Types'
  instance Storable CClock -- Defined in `Foreign.C.Types'
  instance Storable CDouble -- Defined in `Foreign.C.Types'

Couldn't match expected type `a2' with actual type `Int'
  `a2' is a rigid type variable bound by
       a type expected by the context: Storable a2 => a2

その他 ...

次に、いくつかのデータ型を作成します

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes, ExistentialQuantification, ImpredicativeTypes #-}

data AnyStorable = forall a. Storable a => AnyStorable a

pokeMany :: Ptr b -> Int -> [AnyStorable] -> IO ()
pokeMany _ _ [] = return ()
pokeMany ptr offset (AnyStorable x:xs) = do
    pokeByteOff ptr offset x
    pokeMany ptr (offset + sizeOf x) xs

somePoke :: Ptr a -> Int -> Int -> IO ()
somePoke ptr n c = pokeMany ptr 0 [AnyStorable n, AnyStorable c, AnyStorable 'a']

上記のコードにはコンパイル エラーはありません。

pokeManyAnyStorable のような新しいデータ型を作成せずに関数を記述できますか?

4

1 に答える 1

1

要するに、いいえ。そのために必要なのはexists、コレクションにマップされる関数のシグネチャを指定するキーワードです。データ型で使用forallすると、反対側から同じことを効果的に表現できます。

ところで、AnyStorableのインスタンスを作成することを検討してくださいStorable

于 2016-07-08T07:52:02.100 に答える