[Haskell-cafe] Representing record subtypes, sort of.

Kannan Goundan kannan at cakoose.com
Tue Nov 11 01:44:05 UTC 2014


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!



More information about the Haskell-Cafe mailing list