编译
byte_list_to_storable :: Storable a => [CUChar] -> MaybeT IO a
byte_list_to_storable byte_list = do
let
size_of_storable = sizeOf (undefined :: a)
when (length byte_list /= size_of_storable) mzero
liftIO . alloca $ pointer -> do
forM (zip [0 .. size_of_storable - 1] byte_list)
((index, byte) -> pokeByteOff pointer index byte)
peek pointer
失败与
Ambiguous type variable `a0' in the constraint:
(Storable a0) arising from a use of `sizeOf'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: sizeOf (undefined :: a)
In an equation for `size_of_storable':
size_of_storable = sizeOf (undefined :: a)
In the expression:
do { let size_of_storable = sizeOf (undefined :: a);
when (length byte_list /= size_of_storable) mzero;
liftIO . alloca $ pointer -> do { ... } }
尽管有显式类型注释。它可以通过虚拟参数修复:
byte_list_to_storable :: Storable a => a -> [CUChar] -> MaybeT IO a
byte_list_to_storable dummy byte_list = do
let
size_of_storable = sizeOf dummy
但是,byte_list_to_storable
将不得不一直被称为byte_list_to_storable undefined ...
。有没有办法在没有虚拟论证的情况下解决歧义?
Haskell类型变量,就像你的a
一样,默认情况下只存在于一个特定的类型签名中。当你再往下写sizeOf (undefined :: a)
时,在函数定义中,GHC不会以任何方式将此a
与MaybeT IO a
中的相关联,而是将其解释为一个全新的,不受约束的类型变量。
更改此设置的方法是打开ScopedTypeVariables
:
{-# LANGUAGE ScopedTypeVariables #-}
byteListToStorable :: forall a . Storable a => [CUChar] -> MaybeT IO a
byteListToStorable bytelist = do
let sizeOfStorable = sizeOf (undefined :: a)
...