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

Evan Laforge qdunkan at gmail.com
Tue Nov 11 05:46:26 UTC 2014


I would probably write

data Common = Common { ... }
data File = File { fileCommon :: Common, ... }
data Folder = Folder { folderCommon :: Common, ... }
data Entry = EntryFile File | EntryFolder Folder

entry f g (EntryFile a) = f a
entry f g (EntryFolder b) = g b
common = entry fileCommon folderCommon

This is essentially your second approach, but with less scaffolding.

You can pass a Folder to a function wanting an Entry just by composing
EntryFile on the front.

The GADT approach would work too, I suppose, maybe even nicer than mine.

On Mon, Nov 10, 2014 at 5:44 PM, Kannan Goundan <kannan at cakoose.com> wrote:
> 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!
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe


More information about the Haskell-Cafe mailing list