Have you considered a type class and new types ? :-)<span></span><br><br>On Saturday, April 19, 2014, Merijn Verstraaten <<a href="mailto:merijn@inconsistent.nl">merijn@inconsistent.nl</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word">After some thinking it'd be possible to implement this using a quasiquoter and pattern synonyms, however you'd lose the ability to get exhaustiveness checks for the pattern synonyms. Would people be equally opposed to the idea of defining a "closed" set of synonyms? That is a user defines a set of synonyms 'Foo', 'Bar', 'Baz' and a function defined on all three is considered exhaustive regardless of the underlying type. Otherwise using synonyms as abstract constructors for such enum types will result in rather confusing warning of functions not being exhaustively defined.<div>
<br></div><div>Cheers,</div><div>Merijn<div><br><div><div>On Apr 17, 2014, at 18:06 , John Lato wrote:</div><blockquote type="cite"><p dir="ltr">I wouldn't be keen on adding such a specific feature to the language either.  Another concern is that this proposal doesn't seem to address a very common use case for C enums, bit vectors.  IMHO any FFI proposal for working with C enums should take that idiom into account.</p>


<div>On Apr 17, 2014 7:19 AM, "Merijn Verstraaten" <<a>merijn@inconsistent.nl</a>> wrote:<br type="attribution"><blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Cross-post to haskell-prime in case there's any interest for including this into the report's FFI specification.<br>
<br>
Proposal - Foreign enum support<br>
===============================<br>
<br>
At the moment the FFI does not have a convenient way with interacting enums<br>
(whether proper enums or CPP defines) in C (like languages). Both enums and CPP<br>
defined enums are major parts of large C APIs and they are thus crucial to<br>
writing foreign bindings. A few examples:<br>
<br>
SDL_image defines the following enum:<br>
<br>
    typedef enum {<br>
        IMG_INIT_JPG = 0x00000001,<br>
        IMG_INIT_PNG = 0x00000002,<br>
        IMG_INIT_TIF = 0x00000004,<br>
        IMG_INIT_WEBP = 0x00000008<br>
    } IMG_InitFlags;<br>
<br>
OpenCL specifies the following typedefs + CPP defined enum:<br>
<br>
    typedef uint32_t  cl_uint     __attribute__((aligned(4)));<br>
    typedef cl_uint   cl_platform_info;<br>
<br>
    /* cl_platform_info */<br>
    #define CL_PLATFORM_PROFILE                         0x0900<br>
    #define CL_PLATFORM_VERSION                         0x0901<br>
    #define CL_PLATFORM_NAME                            0x0902<br>
    #define CL_PLATFORM_VENDOR                          0x0903<br>
    #define CL_PLATFORM_EXTENSIONS                      0x0904<br>
<br>
OpenCL functions will return the above CPP defines as return values of type<br>
cl_platform_info.<br>
<br>
Current Solutions<br>
-----------------<br>
<br>
In many cases someone wrapping such a C library would like to expose these<br>
enums as a simple sum type as this has several benefits: type safety, the<br>
ability to use haskell constructors for pattern matching, exhaustiveness<br>
checks.<br>
<br>
Currently the GHC FFI, as specified by Haskell2010, only marshalls a small set<br>
of foreign types and newtypes with exposed constructors of these types. As such<br>
there seem two approaches to wrap these enums:<br>
<br>
 1. Implement an ADT representing the enum and write a manual conversion<br>
    function between the ADT and the corresponding C type (e.g. CInt -> Foo and<br>
    Foo -> CInt).<br>
<br>
 2. Use a tool like c2hs to automatically generate the ADT and conversion<br>
    function.<br>
<br>
In both cases the foreign functions are imported using the corresponding C type<br>
in their signature (reducing type safety) and the user is forced write trivial<br>
wrappers for every imported function to convert the ADT to the relevant C type<br>
and back.<br>
<br>
This is both tedious to write and costly in terms of code produced, in case of<br>
c2hs one calls "toEnum . fromIntegral" and "fromIntegral . fromEnum" for every<br>
argument/result even though this could trivially be a no-op.<br>
<br>
Worse, since c2hs uses the Enum class for it's conversion to/from C types it<br>
generates Enum instances like:<br>
<br>
    instance Enum Foo where<br>
        fromEnum Bar = 1<br>
        fromEnum Baz = 1337<br>
<br>
        toEnum 1 = Bar<br>
        toEnum 1337 = Baz<br>
        toEnum unmatched = error ("PlatformInfo.toEnum: Cannot match " ++ show unmatched)<br>
<br>
Since succ/pred and enumFromTo's default implementations assume enums convert<br>
to continuous sequence of Int this means the default generated enum instances<br>
crash. This problem could be overcome by making c2hs' code generation smarter,<br>
but this does not eliminate the tediousness of wrapping all foreign imported<br>
functions with marshalling wrappers, NOR does it eliminate the overhead of all<br>
this useless marshalling.<br>
<br>
Proposal<br>
--------<br>
<br>
Add a new foreign construct for enums, the syntax I propose below is rather<br>
ugly and ambiguous and thereforeopen to bikeshedding, but I prefer explaining<br>
based on a concrete example.<br>
<br>
    foreign enum CInt as Foo where<br>
        Bar = 1<br>
        Baz<br>
        Quux = 1337<br>
        Xyzzy = _<br>
<br>
This would introduce a new type 'Foo' with semantics approximately equivalent<br>
too "newtype Foo = Foo CInt" plus the pattern synonyms "pattern Bar = Foo 1;<br>
pattern Baz = 2; pattern Quux = 1337; pattern Xyzzy = Foo _".<br>
<br>
Explicit listing of the value corresponding to a constructor should be<br>
optional, missing values should just increment by one from the previous (like</blockquote></div></blockquote></div></div></div></div></blockquote>