Haskell 如何确定数据';来自外国代码的构造函数?

Haskell 如何确定数据';来自外国代码的构造函数?,haskell,ffi,Haskell,Ffi,在我的Haskell计划中,我有一个ADT,其中有许多构造函数: data MyData = Con1 | Con2 | ... Con20 我有一个foreign export ccall函数,它将[MyData]封装到StablePtr的数组中。调用它之后,我需要确定用于构造每个元素的构造函数 可以这样解决 foreign export ccall getType :: StablePtr MyData -> IO CInt getType (Con1) =

在我的Haskell计划中,我有一个ADT,其中有许多构造函数:

data MyData = Con1 |
    Con2 |
    ...
    Con20
我有一个
foreign export ccall
函数,它将
[MyData]
封装到
StablePtr的数组中。调用它之后,我需要确定用于构造每个元素的构造函数

可以这样解决

foreign export ccall getType :: StablePtr MyData -> IO CInt
getType (Con1) = return 1
getType (Con2) = return 2
...

但接下来我需要在C头中手动定义这些常量。这很容易出错,所以我想知道是否有办法让GHC为我做这项工作。

为Haskell类型派生
Enum
,并从EnumMyData::MyData->Int导出
;fromEnumMyData=fromEnum


然后,通过查看GHC分配的Int标记,您可以在C端进行案例分析。

我找到了解决方案

我在C代码中将可能的构造函数类型定义为enum:

typedef enum
{
    MyDataCon1,
    MyDataCon2,
    ...
    MyDataCon20
} MyDataConstructor;
然后我在Haskell源代码中使用了enum钩子:

{#enum MyDataConstructor deriving (Show) #}
预处理后,该行变为

data MyDataConstructor = MyDataCon1
    | MyDataCon2
    ...
    | MyDataCon20
现在我可以这样定义
getType

foreign export ccall getType :: StablePtr MyData -> IO CInt
getType md = do
    md' <- deRefStablePtr md
    case md' of
        Con1 -> return $ fromEnum MyDataCon1
        Con2 -> return $ fromEnum MyDataCon2
        ...
        Con20 -> return $ fromEnum MyDataCon20
foreign export ccall getType::StablePtr MyData->IO CInt
getType md=do

对不起,我没听懂。我怎么知道哪个构造函数引用了某个标记?你不知道-它是由枚举顺序给出的。但无论如何,您已经丢失了C端的所有信息,因此您必须依赖不安全的映射。因此,无法自动生成该映射?您正在尝试生成什么映射?GHC已经生成了从Int到'a'和'a'到Int的映射。但是在C端,您不能使用'a'。我希望GHC放置类似于
#define CON1_ID 1
#define CON2_ID 2
。。。导入生成的标题。