
Hi Mateusz, You can write 'Foo :~> [t| Maybe String |] to make the generated code include a type instance App ElF Foo = Maybe String Unfortunately the type of (:~>) includes some un-exported classes, so you have to dig into vinyl's source to see which arguments are actually allowed. I'm not sure exactly what you mean by
PlainRec ElF (ParentId ': '[])” works but is ugly
But maybe it's worth just using the Data.Vinyl.Universe.Field (ex.
http://lpaste.net/109203), if you would rather write
PlainRec ElField '["parent_id" ::: Maybe Integer])
than,
PlainRec ElF '[ParentId]
Or maybe you want to use Symbol together with your own universe:
makeUniverse' ''Symbol "ElF"
semantics ''ElF [ [t| "height" |] :~> [t| Maybe Int |] ]
-- type instance App ElF "height" = Maybe Int -- or just write those by-hand
height = Proxy :: Proxy "height" -- there seems to be no code
generation in Vinyl for these
which will give you a type like
PlainRec ElF '["parent_id"]
Hopefully one of these options is not as ugly as the other.
Regards,
Adam
On Mon, Aug 11, 2014 at 5:43 AM, Mateusz Kowalczyk
Hi,
I'm looking for some help in helping to migrate to vinyl-0.4 from earlier version. I'll first outline how I currently have things set up and then ask a few questions. For reference the whole project is at [1]. You can just skip to questions in the end if you want to.
I have a small project which goes out to a few sites, fetches some similar XML data, parses some fields and returns a data type. My original attempt was to generate a data type per site but that was very ugly: couldn't reuse functions, accessors, anything. So I then turned to vinyl and have the following solution:
I have a bunch of common fields defined like this:
-- file_url ∷ "file_url" ::: String file_url = Field
parent_id ∷ "parent_id" ::: Maybe Integer parent_id = Field -- and so on.
I'm using HXT to process the XML I get from each site so I have created many HXT arrows creating each field like this:
-- parent_idA ∷ (Functor (cat XmlTree), ArrowXml cat) ⇒ cat XmlTree (PlainRec '["parent_id" ::: Maybe Integer]) parent_idA = (parent_id =:) . readMaybe <$> getAttrValue "parent_id" --
Then for each site I define records like this
-- type GelbooruPost = PlainRec '[ "height" ::: Integer , "score" ::: Integer , "file_url" ::: String , "parent_id" ::: Maybe Integer , … ] --
and create the final HXT arrow which will parse and run my value parsers on the whole output
-- parsePost ∷ (Functor (cat XmlTree), ArrowXml cat) ⇒ cat XmlTree GelbooruPost parsePost = hasName "post"
heightA <:+> scoreA <:+> file_urlA <:+> parent_idA <:+> sample_urlA <:+> sample_widthA <:+> sample_heightA <:+> preview_urlA <:+> ratingA <:+> tagsA <:+> idA <:+> widthA <:+> changeA <:+> md5A <:+> creator_idA <:+> has_childrenA <:+> created_atA <:+> statusA <:+> sourceA <:+> has_notesA <:+> has_commentsA <:+> preview_widthA <:+> preview_heightA --
This works OK: I have similar records for each site and vinyl let me use the same accessors to work over the data from each site without much hassle even though they all return slightly different things. But now vinyl-0.4 is out and I have to update but I'm struggling.
As per tutorial I converted all my fields to this format:
-- data Fields = Height | Score | FileUrl | ParentId | SampleUrl | … --
Then generated singletons and made universe:
-- genSingletons [ ''Fields ] makeUniverse' ''Fields "ElF" semantics ''ElF [ 'Height :~> ''String , 'Score :~> ''Integer , 'FileUrl :~> ''String , 'ParentId :~> ''Integer -- Maybe Integer , 'SampleWidth :~> ''Integer , 'SampleHeight :~> ''Integer , 'PreviewUrl :~> ''String , 'Rating :~> ''Rating , 'Tags :~> ''String -- [String] --
As you can see I have a problem here already: I don't know how to specify ‘Maybe Integer’ or ‘[String]’ in the way that is accepted. Previously I would just do "tags ::: [String]" and it worked.
I also wonder what things like:
-- PlainRec '["parent_id" ::: Maybe Integer]) --
now become. “PlainRec ElF (ParentId ': '[])” works but is ugly, is there a shorthand for singletons? This is assuming I can convince the ParentId field to be Maybe Integer.
Lastly I'd like to know why trivial examples such as this
-- a ∷ PlainRec ElF (Score ': '[]) a = SScore =: 7 --
require a type signature. While I put down the signatures anyway, I wonder if there's a way to skip them. I suppose using the field in an annotated record somewhere might let me do this. I imagine the problem here is that we need to specify ElF.
Perhaps I am meant to approach this whole thing differently which is why I laid out the structure a bit rather than just asking about syntax. I have watched the video at [2] and while the new records do sound better, I can't find a good guide on how to use them. The tutorial on GitHub[3] is rather lacking. If someone knows about more guides then I'd love to hear about that too.
Thanks!
[1]: http://github.com/Fuuzetsu/h-booru [2]: http://vimeo.com/102785458 [3]: https://github.com/VinylRecords/Vinyl/blob/master/tests/Intro.lhs
-- Mateusz K. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe