2016-07-08 6 views
1

オブジェクトHaskellの異種のリストは、私が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'] 

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

AnyStorableのような新しいデータ型を作成せずにpokeMany関数を書くことはできますか?

答えて

1

要するに、そのために必要なのは、コレクションにマップされる関数の署名を指定するキーワードexistsです。データ型にforallを使用すると、他の側からも同じことが効果的に表現されます。

ところで、AnyStorableStorableのインスタンスにすることを検討することがあります。

+0

もちろん、あなたは正しいです。 'AnyStorable'は' Storable'のインスタンスでなければなりません。 – Bet

関連する問題