Haskell:使用sizeOf时可存储中的类型变量不明确

Haskell:使用sizeOf时可存储中的类型变量不明确,haskell,Haskell,汇编 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

汇编

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\u list\u to\u storable
必须始终被称为
byte\u list\u to\u 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)
     ...

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)
     ...

你想在这里干什么?你希望从哪里推断出
a
的类型呢?@code Guru我正在从字节列表中构造一个可存储的值。列表应该有正确的长度,这就是为什么我需要使用
sizeOf
获得我正在构建的值类型的大小。
a
的类型在调用
byte\u list\u to\u storable
时指定,例如
value::FunPtr(IO())是未定义的
部分,它只是存根尚未完成的内容?@code Guru否,它不是存根。我们必须给
sizeOf
一个值,即使它不以任何方式检查它。所以,当我们没有任何值时,我们使用未定义的
?你希望从哪里推断出
a
的类型呢?@code Guru我正在从字节列表中构造一个可存储的值。列表应该有正确的长度,这就是为什么我需要使用
sizeOf
获得我正在构建的值类型的大小。
a
的类型在调用
byte\u list\u to\u storable
时指定,例如
value::FunPtr(IO())是未定义的
部分,它只是存根尚未完成的内容?@code Guru否,它不是存根。我们必须给
sizeOf
一个值,即使它不以任何方式检查它。所以,当我们没有任何值时,我们使用
未定义的
。现在它可以工作了,谢谢!实际上,我启用了
ScopedTypeVariables
,所以答案似乎只是为所有a添加
。您说过,默认情况下,任何签名中的类型变量只引用该特定签名,因此为所有a添加
会使函数的类型签名中的类型变量也引用其定义。这就是它的工作原理吗?@myrix是的,没错。扩展只允许为所有a b c。。。对于要在函数体上确定作用域的每个类型变量。感谢@Sarah!的确认!现在它工作了,谢谢!实际上,我启用了
ScopedTypeVariables
,所以答案似乎只是为所有a添加
。您说过,默认情况下,任何签名中的类型变量只引用该特定签名,因此为所有a添加
会使函数的类型签名中的类型变量也引用其定义。这就是它的工作原理吗?@myrix是的,没错。扩展只允许为所有a b c。。。对于要在函数体上确定作用域的每个类型变量。感谢@Sarah!的确认!