Re: [Haskell-cafe] Re: Adding a field to a data record

2009-07-29 Thread Lennart Augustsson
With the RecordWildCard extension you should be able to write

newFoo Old.Foo{..} = New.Foo { .., z=1 }



On Tue, Jul 28, 2009 at 3:47 PM, Henry Laxennadine.and.he...@pobox.com wrote:
 Malcolm Wallace Malcolm.Wallace at cs.york.ac.uk writes:


  and perhaps use emacs to
  query-replace all the Foo1's back to Foo's

 At least this bit can be avoided easily enough, by using
 module qualification during the conversion process.

      module Original (Foo(..)) where
      data Foo = Foo { ... y :: Int } deriving ...

      module New (Foo(..)) where
      data Foo = Foo { ... y, z :: Int } deriving ...

      module Convert where
      import Original as Old
      import New as New
      newFoo :: Old.Foo - New.Foo
      newFoo old{..} = New.Foo { a=a, b=b, ... z=1 }

 Finally rename module New.

 Regards,
      Malcolm


 Thanks Malcolm, yes, that keeps me out of emacs, but the part I would really
 like to avoid is writing the New.Foo { a=a, b=b, ... z=1 } part, where the 
 field
 names are many, long, and varied.  Yes, I could cut and paste, but I'm hoping
 for a better way.  Thanks.
 Best wishes,
 Henry Laxen


 ___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: Adding a field to a data record

2009-07-28 Thread Jason Dagit
On Tue, Jul 28, 2009 at 7:47 AM, Henry Laxen nadine.and.he...@pobox.comwrote:

 Malcolm Wallace Malcolm.Wallace at cs.york.ac.uk writes:

 
   and perhaps use emacs to
   query-replace all the Foo1's back to Foo's
 
  At least this bit can be avoided easily enough, by using
  module qualification during the conversion process.
 
   module Original (Foo(..)) where
   data Foo = Foo { ... y :: Int } deriving ...
 
   module New (Foo(..)) where
   data Foo = Foo { ... y, z :: Int } deriving ...
 
   module Convert where
   import Original as Old
   import New as New
   newFoo :: Old.Foo - New.Foo
   newFoo old{..} = New.Foo { a=a, b=b, ... z=1 }
 
  Finally rename module New.
 
  Regards,
   Malcolm
 

 Thanks Malcolm, yes, that keeps me out of emacs, but the part I would
 really
 like to avoid is writing the New.Foo { a=a, b=b, ... z=1 } part, where the
 field
 names are many, long, and varied.  Yes, I could cut and paste, but I'm
 hoping
 for a better way.  Thanks.


I guess you could define:
type UpgradeFoo = (Foo, Int)

And then write the conversion code as a zip.  upgradeFoo foos = zip foos
[1..]

instance Show UpgradeFoo where ...

And then use the module trick to switch the code around?

Jason
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: Adding a field to a data record

2009-07-28 Thread Malcolm Wallace

the part I would really like to avoid is writing the
New.Foo { a=a, b=b, ... z=1 } part, where the field
names are many, long, and varied.


OK, here is another hack-ish trick, since I notice your data is stored  
on disk as text, using show.  I assume you are using something like  
Read to retrieve it.  Well, how about using a real parser instead?   
The parser during conversion can be slightly more lax, automatically  
adding in the extra field.


For instance, using polyparse's Text.Parse, and DrIFT to derive the  
appropriate Parse instance for your datatype:


module Foo where
data Foo = Foo { a :: Int
   , b :: Bool
   , c :: Maybe Foo }
  {-! derive : Parse !-}

DrIFT gives you this instance:

{-* Generated by DrIFT : Look, but Don't Touch. *-}
instance Parse Foo where
parse = constructors
[ ( Foo
  , return Foo `discard` isWord { `apply` field a
   `discard` isWord , `apply` field b
   `discard` isWord , `apply` field c
   `discard` isWord }
  )
]

Let's say the field 'b' is new, and your existing data does not have  
it.  So just take the parser generated by DrIFT and make a small  
modification:


{-* Generated by DrIFT but modified by hand for conversion  
purposes *-}

instance Parse Foo where
parse = constructors
[ ( Foo
  , return Foo `discard` isWord { `apply` field a
   `apply` return True -- this field does not yet exist in 
data
   `discard` isWord , `apply` field c
   `discard` isWord }
  )
]

Then do the obvious thing: parse the old data, immediately write it  
out again, and then throw away the modified parser in favour of the  
pure generated one.


Regards,
Malcolm
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: Adding a field to a data record

2009-07-28 Thread Iavor Diatchki
Hello,
you may also find the package pretty-show
(http://hackage.haskell.org/package/pretty-show) useful.  It contains
code to convert automatically derived instances of Show into an
explicit data structure, which you can then manipulate (e.g., by
adding the extra field), and then render back to text.
-Iavor


On Tue, Jul 28, 2009 at 6:07 PM, Malcolm
Wallacemalcolm.wall...@cs.york.ac.uk wrote:
 the part I would really like to avoid is writing the
 New.Foo { a=a, b=b, ... z=1 } part, where the field
 names are many, long, and varied.

 OK, here is another hack-ish trick, since I notice your data is stored on
 disk as text, using show.  I assume you are using something like Read to
 retrieve it.  Well, how about using a real parser instead?  The parser
 during conversion can be slightly more lax, automatically adding in the
 extra field.

 For instance, using polyparse's Text.Parse, and DrIFT to derive the
 appropriate Parse instance for your datatype:

    module Foo where
    data Foo = Foo { a :: Int
                   , b :: Bool
                   , c :: Maybe Foo }
      {-! derive : Parse !-}

 DrIFT gives you this instance:

    {-* Generated by DrIFT : Look, but Don't Touch. *-}
    instance Parse Foo where
        parse = constructors
            [ ( Foo
              , return Foo `discard` isWord { `apply` field a
                       `discard` isWord , `apply` field b
                       `discard` isWord , `apply` field c
                       `discard` isWord }
              )
            ]

 Let's say the field 'b' is new, and your existing data does not have it.  So
 just take the parser generated by DrIFT and make a small modification:

    {-* Generated by DrIFT but modified by hand for conversion purposes *-}
    instance Parse Foo where
        parse = constructors
            [ ( Foo
              , return Foo `discard` isWord { `apply` field a
                       `apply` return True -- this field does not yet exist
 in data
                       `discard` isWord , `apply` field c
                       `discard` isWord }
              )
            ]

 Then do the obvious thing: parse the old data, immediately write it out
 again, and then throw away the modified parser in favour of the pure
 generated one.

 Regards,
    Malcolm
 ___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe