How to connect "user input text formula" and yesod entity?

77 views
Skip to first unread message

Magicloud Magiclouds

unread,
Apr 23, 2013, 11:44:31 PM4/23/13
to yeso...@googlegroups.com
Hi, this was mentioned in my yesterday topic. But the more I thought about it, the more I found it impossible. So I am seeking help on how to make this happen under Yesod framework.

Say I was making a data presentation site. The data was parsed and stored with yesod framework. So the data in database was totally yesod style (the names, the id, etc).

At first, I made a template, put a few html/javascript chart widgets on it. And made a handler to get entities from database then caculate and encode the data to send to the widgets. Everything worked until I had more charts to add.

Problem here is, the data was not changed. But everytime a chart needs to be added, I'd have to modify the handler, the template. So I am thinking, why not I just give out the formulas and some fixed policies (like caculate the formulas by day). Then let the system to parse the formulas, fetch the data, put charts on webpage, all dynamicly? Then I could even make a page to manage all the formulas. When the users need new charts, they just input the formulas.

Then I was stuck. How could I connect formulas with entities? For example "Person["magicloud"].age", since I do not want to get the same record again and again, so I use raw SQL to get "magicloud :: Person" and cache it. Then how could I return "personAge magicloud" without a huge case like

case attr of
  "age" -> PersistInt . personAge
  "name" -> PersistText . personName
  ...
--
竹密岂妨流水过
山高哪阻野云飞

And for G+, please use magiclouds#gmail.com.

Greg Weber

unread,
Apr 24, 2013, 5:08:46 PM4/24/13
to Yesod Web Framework
It is still difficult to understand at least for me to understand what you are trying to do. Maybe you can just show the code for what you have now/what you think you need to write (like you do at the end of this message but a little more extensive) and show some pseudo code for what you would like to write.


--
You received this message because you are subscribed to the Google Groups "Yesod Web Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to yesodweb+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Magicloud Magiclouds

unread,
Apr 24, 2013, 10:57:09 PM4/24/13
to yeso...@googlegroups.com
Let me try here:

when user input "Item.googleglass.received - Item.googleglass.sent", which means he wants a chart of stocked Google Glass everyday. I should run code like:

  item <- runDB $ selectList [ ItemName ==. "googleglass", ItemDay ==. last7days ] [Desc ItemDay]
  drawChart $ map (\i -> itemReceived i - itemSent i) item

Parsing the user input is done, I got like "Token (Table "Item") (Filter "googleglass") (Field "received")". Then is my problem: How could I convert from Token to the code above? I mean I do not know how to get haskell token "itemReceived" from text "Item" and "received".

I am think writing a little compiler thing that embeded into my project and deal with the formula like it is a script for my web site. But that is too complex for a website....

Michael Snoyman

unread,
Apr 25, 2013, 2:51:15 AM4/25/13
to yeso...@googlegroups.com
You'd have to have a function that knows to convert "Item" and "received" into "itemReceived". You'd essentially be recreating dynamic typing/late binding in Haskell. It's certainly possible, though will admittedly be more tedious than using it as a built-in language feature in Python or Ruby.

Magicloud Magiclouds

unread,
Apr 25, 2013, 3:07:04 AM4/25/13
to yeso...@googlegroups.com
That is my point! Maybe lacking of reflection is the root cause. Then definitely there is no easy way....

Greg Weber

unread,
Apr 25, 2013, 10:35:38 AM4/25/13
to Yesod Web Framework
It seems that there are limited options so you would want the user to be auto-completing and sending back ids. You would still need another table representing the queryable columns. In a dynamic language you could eval what the id corresponds to. If the columns don't change though you don't have to use a table and can just have a memory structure with what the id maps to.

Magicloud Magiclouds

unread,
Apr 26, 2013, 3:00:38 AM4/26/13
to yeso...@googlegroups.com
So is there a hook, that I could write some code called when yesod generates Entities from models to also generate a text table for me?

Michael Snoyman

unread,
Apr 26, 2013, 3:03:25 AM4/26/13
to yeso...@googlegroups.com
You'd have to do this in Template Haskell since you're generating code. You can add arbitrary functions to the share statement in Model.hs.

Magicloud Magiclouds

unread,
Jun 25, 2013, 9:55:40 PM6/25/13
to yeso...@googlegroups.com
Just got time to work on this. I've done the parsing and framework with rawSql. But there is still one thing missed.

Since the user could require any entities, which means the same process would return various entity types.

This is the problem, no matter rawSql or selectList, without ScopedTypeVariables and constraints like "Asc EntityName", how could they know which table to require and which entity type to return?

And if this is impossible, how to query to JSON Value? Which is my last solution now....

Magicloud Magiclouds

unread,
Jun 26, 2013, 1:50:08 AM6/26/13
to yeso...@googlegroups.com
Before any answer came up, I used HList to make the table like this:

hsNames = [ ("user", [ ("ident", UserIdent), ("password", UserPassword) ]) ]

So when the formula requires "user.magicloud.password", I successfully turned it into:

let tn = hsNames .!. user .!. "ident"
selectList [ tn ==. "magicloud" ]

This part seemed smooth until I compiled it, and got:

    Couldn't match type `PersistEntityBackend val0'
                  with `persistent-1.2.1:Database.Persist.Sql.Types.SqlBackend'
    The type variable `val0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Expected type: PersistMonadBackend
                     (persistent-1.2.1:Database.Persist.Sql.Types.SqlPersistT
                        (HandlerT App IO))
      Actual type: PersistEntityBackend val0
    In the expression:
      selectList [tn ==. n, tt <=. twoweeksago] [Asc tt]
    In the expression:
      let
        tn = hsNames .!. t .!. "name"
        tt = hsNames .!. t .!. "cutime"
      in selectList [tn ==. n, tt <=. twoweeksago] [Asc tt]
    In the first argument of `mapM', namely
      `(\ (t, n)
          -> let
               tn = hsNames .!. t .!. "name"
               tt = hsNames .!. t .!. "cutime"
             in selectList [tn ==. n, tt <=. twoweeksago] [Asc tt])'

Reply all
Reply to author
Forward
0 new messages