|
From: Bjorn B. <bj...@br...> - 2009-07-24 06:32:41
|
Yes, don't declare a type for the query, let the type checker infer it.
/Bjorn
2009/7/24 Artyom Shalkhakov <art...@gm...>:
> Hi Justin,
>
> It's a pity I can't test the code ATM, but isn't there a way
> to find "the most general type" of the query?
>
> Anyway, thanks for clarifying that. Next time, I will have to check
> the code I post.
>
> 2009/7/23 Justin Bailey <jgb...@gm...>:
>> Looking at your example:
>>
>>>> q val = do
>>>> s <- table stock
>>>> restrict (fromNull (constant "") (s!company_name)
>>>> `like` constant ("%"++val++"%"))
>>>> r <- project (company_name << s!company_name #
>>>> ticker << s!ticker)
>>>> return r
>>
>>
>> The type of q would be based on the columns projected. Assuming
>> company_name and ticker are both strings, you would get
>>
>> q :: Query (Rel (RecCons (CompanyName (Expr String)) (RecCons
>> (Ticker (Expr String)) RecNil)
>>
>> That is, a type-level tuple which indicates that the query has two
>> columns, CompanyName and Ticker, both with type String.
>>
>> Simplying your next example a little bit, I can show that it won't type check:
>>
>>>> flds cond2 s = let a = (vendor_name << s!vendor_name) # fld
>>>> b = if cond2
>>>> then (customer_id << s!customer_id) # a
>>>> else a
>>>> in b
>>>> where
>>>> fld = company_name << s!company_name # ticker << s!ticker
>>
>> What is the type of b? We have to look at the query created. When
>> cond2 is true, then b is:
>>
>> (customer_id << s!customer_id) # (vendor_name << s!vendor_name) #
>> company_name << s!company_name # ticker << s!ticker
>>
>> However, if cond2 is false then b is:
>>
>> (vendor_name << s!vendor_name) # company_name << s!company_name #
>> ticker << s!ticker
>>
>> If cond2 is true, then the type of b can determined by the query shape:
>>
>> b :: RecCons (CustomerId (Expr Int)) (RecCons (VendorName (Expr
>> String)) (RecCons (CompanyName (Expr String) (...))
>>
>> However, if cond2 is false then the type is
>>
>> b :: RecCons (VendorName (Expr String)) (RecCons (CompanyName (Expr
>> String) (...))
>>
>> Since the type of the "then" and "else" arms need to agree, this won't
>> compile. Its like writing
>>
>> b = if True then "a" else 1
>>
>> On Thu, Jul 23, 2009 at 1:37 AM, Artyom
>> Shalkhakov<art...@gm...> wrote:
>>> Hi,
>>>
>>> 2009/7/22 Keren Lenz <ker...@gm...>:
>>>> Here is an example (in imperative psudo code of what I mean by dynamic
>>>> query:
>>>> Query generate(bool cond1, bool cond2) {
>>>> Colums c = null;
>>>> if(cond1)
>>>> c.add(col1);
>>>> if(cond3)
>>>> c.add(col2);
>>>> Query q = SELECT + c + FROM table_name;
>>>> return q;
>>>> }
>>>
>>>
>>>
>>>> That is, the selected columns are chosen based on runtime conditions.
>>>> Is that possible with HaskellDB?
>>>
>>> I would like to stress how HaskellDB works. You are given atomic building
>>> blocks (relations, tuples and fields) and some combinators ("glue" that helps
>>> you combine your building blocks: relational and query operations). What you
>>> are really doing with HaskellDB is manipulating an abstract syntax tree of a DSL
>>> embedded in Haskell.
>>>
>>> A simple example would be something along these lines [1]:
>>>
>>>> q val = do
>>>> s <- table stock
>>>> restrict (fromNull (constant "") (s!company_name)
>>>> `like` constant ("%"++val++"%"))
>>>> r <- project (company_name << s!company_name #
>>>> ticker << s!ticker)
>>>> return r
>>>
>>> It is already somewhat "dynamic". Can we do anything to make it more "dynamic"?
>>> Yes, we can:
>>>
>>>> q flds val = do
>>>> s <- table stock
>>>> restrict (fromNull (constant "") (s!company_name)
>>>> `like` constant ("%"++val++"%"))
>>>> r <- project (flds s)
>>>> return r
>>>
>>> where flds is simply
>>>
>>>> flds s = company_name << s!company_name # ticker << s!ticker)
>>>
>>> So now you can do:
>>>
>>>> flds cond1 cond2 s = let a = if cond1
>>>> then (vendor_name << s!vendor_name) # fld
>>>> else fld
>>>> b = if cond2
>>>> then (customer_id << s!customer_id) # a
>>>> else a
>>>> in b
>>>> where
>>>> fld = company_name << s!company_name # ticker << s!ticker
>>>
>>> (don't forget to change the definition of q!)
>>>
>>> As the number of conditions grows, this style becomes very inconvenient to
>>> program in, so you'd need a writer monad over a monoid or something I suppose.
>>>
>>> Also, I would like to note that I haven't tested the code given above,
>>> so I don't
>>> know if there are any bugs or not. But feel free to ask if there are,
>>> anyway. :-)
>>>
>>> Cheers,
>>> Artyom Shalkhakov.
>>>
>>> [1] http://pseudofish.com/blog/2008/05/11/haskelldb-basics/
>>>
>>> ------------------------------------------------------------------------------
>>> _______________________________________________
>>> Haskelldb-users mailing list
>>> Has...@li...
>>> https://lists.sourceforge.net/lists/listinfo/haskelldb-users
>>>
>>
>
> ------------------------------------------------------------------------------
> _______________________________________________
> Haskelldb-users mailing list
> Has...@li...
> https://lists.sourceforge.net/lists/listinfo/haskelldb-users
>
|