[Haskell-cafe] Updating code to work with vinyl 0.4
vogt.adam at gmail.com
Mon Aug 11 15:04:47 UTC 2014
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
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])
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.
On Mon, Aug 11, 2014 at 5:43 AM, Mateusz Kowalczyk
<fuuzetsu at fuuzetsu.co.uk> wrote:
> 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 .
> 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_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  and while the new records do sound better,
> I can't find a good guide on how to use them. The tutorial on GitHub
> is rather lacking. If someone knows about more guides then I'd love to
> hear about that too.
> : http://github.com/Fuuzetsu/h-booru
> : http://vimeo.com/102785458
> : https://github.com/VinylRecords/Vinyl/blob/master/tests/Intro.lhs
> Mateusz K.
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
More information about the Haskell-Cafe