
I have an API that, in a language with subtyping, would look like: class FsEntry id: String class FsFile extends FsEntry modified: Date size: Int class FsFolder extends FsEntry owner: String listFolder :: Path -> [FsEntry] createFile :: Path -> FsFile createFolder :: Path -> FsFolder (I'm assuming some way of specifying that FsEntry will only ever have those two subtypes.) How would you represent this in Haskell? My first thought was: newtype FsEntry = FsEntry FsCommon FsExtra data FsCommon = FsCommon { id: String } data FsExtra = FsFile { modified: Date, size: Int } | FsFolder { owner: String } But then I couldn't have precise return types for `writeFile` and `createFolder`. My next attempt was to use a type-parameterized top-level class: data FsCommon = FsCommon { id: String } data FsFileExtra = FsFileExtra { modified: Data, size: Int } data FsFolderExtra = FsFolderExtra { owner: String } data FsEither = FsFile FsFileExta | FsFolder FsFolderExtra newtype FsEntryBase extra = FsEntryBase FsCommon extra type FsEntry = FsEntryBase FsEither type FsFile = FsEntryBase FsFileExtra type FsFolder = FsEntryBase FsFolderExtra 1. This seems complicated. 2. I can't pass an `FsFolder` to a function expecting an `FsEntry`, but maybe that's just the nature of having subtyping and I have to give up on that (which I'm ok with). Any suggestions on how to do this? Thanks!