Gabriella439 / optparse-generic

Auto-generate a command-line parser for your datatype
BSD 3-Clause "New" or "Revised" License
208 stars 32 forks source link

Options with newtypes #10

Open deepfire opened 8 years ago

deepfire commented 8 years ago

How does one provide for using newtypes as option record types?

Currently the failure mentions missing ParseFields instance, but when one tries to provide a hand-written one, along the lines of the existing ParseField instances, one faces the fact that parseString is not exported.

Are there plans to automate instances for newtypes? Or to document how to define ParseFields instances for own types?

Gabriella439 commented 8 years ago

Couldn't you use GeneralizedNewtypeDeriving to automate deriving the instance?

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

newtype Foo = Foo { getFoo :: Bar } deriving (ParseRecord)
deepfire commented 8 years ago

Gabriel Gonzalez notifications@github.com writes:

Couldn't you use GeneralizedNewtypeDeriving to automate deriving the instance?

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

newtype Foo = Foo { getFoo :: Bar } deriving (ParseRecord)

This almost works, indeed:

newtype PAlias = PAlias { from ∷ String }
    deriving ( -- unrelated instances
              Generic, Show
               -- instances for optparse-generic
             , ParseRecord, ParseFields, ParseField, Read)

data Params where
    Params
        ∷ {
      project_id           ∷ PAlias
    } → ReportParams
    deriving (Generic, Show)

instance ParseRecord ReportParams

However:

  1. I have to add four deriving clauses (the last four ones)
  2. It no longer accepts an argument -- usage is printed
  3. The usage for the option is printed like:
     --project_id PALIAS

..instead of:

     --project_id STRING
  1. I already have DeriveAnyClass, which I am unable to get rid of, which clashes with GND at least in case of FromJSON (it says so)
  2. For completeness, here is the list of language pragmas I use:

{-# LANGUAGE Arrows #-} {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableSuperClasses #-} {-# LANGUAGE UnicodeSyntax #-}

  1. I can extract a minimal testcase a bit later, after I get some sleep : -)
Gabriella439 commented 8 years ago

In the worst case you can just hand-write the instance, which would be:

instance ParseField PAlias where
    parseField m = fmap PAlias (parseField m)