Different Types signature on Different OS

I’m trying to build the same version of the Haskell program in Linux Ubuntu and macOS Monterey (M1) but facing a strange issue.

CMode From module System.Posix.Types have different signatures.

– mac

System.Posix.Types> :t CMode
CMode :: Word16 -> CMode


System.Posix.Types> :t CMode
CMode :: Word32 -> CMode

both has same stack resolver: lts-17.12
same ghc version 8.10.4
Identical Stack dependencies List
using same version of base
in documentation CMode has Word32 Signature

but somehow on mac CMode has different Signature
CMode :: Word16 → CMode

Please suggest what I’m doing wrong, if possible provide detailed solution.

Yes. They are different on different OS:

Haskell equivalents of the types defined by the <sys/types.h> C header on a POSIX system.

This module contains platform specific information about types. As such the types presented on this page reflect the platform on which the documentation was generated and may not coincide with the types on your platform.

if possible provide detailed solution.

Yes, the types can be different. But what’s exactly the problem? If you’re putting platform types into your data, then you need to convert them first or use a higher level wrapper.

1 Like

thanks for your quick response.

means GHC is not that much cross-platform.
I can understand the reason behind it, (to improve performance, if not please describe)
I’m using word32 in my data model and CMode is word16 should I still go with Word32 as a Higher level wrapper?

to convert from word* to word* I’m thinking about using

toWord = fromInteger . toInteger

please suggest am I doing correct?

Note that unix is not part of GHC. The unix package is not portable, but that is no secret.

You can just use fromIntegral (which is defined as fromInteger . toInteger).

1 Like

Note that unix is not part of GHC. The unix package is not portable, but that is no secret.

correct me if I’m wrong, System.Posix.Types is from base package. not from Unix

1 Like

Is there a way to use a #if $ARCH == Foo macro here?

1 Like

A related question from Reddit.


You’re right, I should have known as I looked at that recently.

I don’t actually know why that module is exposed in base. It kind of reminds me of this GHC issue about GHC.Exts and related modules.

if os(xyz)
  hs-source-dirs: platform-dep/xyz

↑ I find slightly less dirty than C macros. @aammfe if you tell us exactly what your goal is, people can provide more creative solutions.


@f-a my end goal is to compile a code base with dataType like this
data MyAppFileModes = Mode Word32
there is a type miss-match when trying to compile on mac, bcs it depends upon System.Posix.Types.CMode(Word32) and CMode Depend upon OS

I’m going to use @jaror solution, it’s simple, and most probably when fromIntegral is not required (CMode uses Word32 instead of Word16) GHC will remove this function call during optimizations.
need to test it.

That’s the current problem you’re trying to solve, but I doubt that is really your end goal. Where are you getting that CMode from and what do you want to do with the information you get from it?

fromIntegral will indeed be optimized away when used on a concrete type like CMode. But I don’t think this will be a bottleneck in your program either way.


It is. But FFI types by necessity aren’t. They are literally the bridge between the platform-abstracted and platform-specific code. By using them in your code you get entangled with this. Your code is now platform-specific too!

But that’s okay. The thing that can be a real bother is that such types are unmarked and you may not even know that someone in your upstream is using them.

Perhaps they should be opaque types with some basic interfaces attached: data CMode = forall a . (Storable a, Integral a, ...) => CMode a or something. But that has its own trade-offs.

1 Like