
Also, note that it's really easy to hide all the CPP uglyness in a single file, or do it with Makefiles, or something along those lines. By the way, you don't want to use typeclasses here; they solve the problem of having more than one possible interface at runtime, whereas you only care about compile-time. The easiest way to solve that problem is through the module system. An example follows. with this directory tree: System/Abstraction.hs System/Abstraction/POSIX.hs System/Abstraction/Windows.hs in System/Abstraction.hs: module System.Abstraction ( #if POSIX module System.Abstraction.POSIX #elsif WINDOWS module System.Abstraction.Windows #endif ) where #if POSIX import System.Abstraction.POSIX #elsif WINDOWS import System.Abstraction.Windows #else #error Unknown system type #endif Now you can write POSIX.hs and Windows.hs independently to implement whatever OS/foreign interface you care about, and your other code can import System.Abstraction without needing -cpp. Alternatively you can make POSIX.hs and Windows.hs just declare themselves as "module System.Abstraction" and use your build system to compile the correct one.