How to define data constructor from external code?

In my Haskell program, I have an ADT with many constructors:

data MyData = Con1 |
    Con2 |
    ...
    Con20

I have a function foreign export ccallthat wraps [MyData]in an array StablePtr's. After calling it, I need to determine which constructor was used to build each element.

It can be solved this way.

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

but then I will need to manually define these constants in the C header. This is error prone, so I wonder if there is a way to get GHC to do this work for me.

+5
source share
2 answers

I found a solution for this.

I defined the possible types of constructors as an enumeration in my C code:

typedef enum
{
    MyDataCon1,
    MyDataCon2,
    ...
    MyDataCon20
} MyDataConstructor;

C- > Haskell Haskell:

{#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
0

Enum Haskell fromEnumMyData :: MyData -> Int ; fromEnumMyData = fromEnum.

C, GHC Int.

+5

All Articles