You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Today a from ... group ... [compute ...] query returns a list. If the group key is empty (i.e. group is immediately followed by compute, or group marks the end of the from expression) then the list will have one element. You can use only (which was added in #62):
# Current syntax
= only (from e in scott.emp group compute sum of e.sal);
val it = 29025.0 : real
= only (from e in scott.emp group compute sum of e.sal, count);
val it = {count=14,sum=29025.0} : {count:int, sum:real}
= only (from e in scott.emp group);
val it = () : unit
But it is rather circuitous to first build a list with a single element, and then strip away the list. We just wanted to aggregate the elements.
In functional programming parlance, we want to fold the elements. A type that knows how to fold elements into one is called a monoid. SQL aggregate functions (e.g. SUM, COUNT, MIN, MAX) are generally monoids. So are the boolean operations AND, OR and XOR. In Comprehending Monoids with Class, Perreaux makes the case that a monoid comprehension is more powerful and general than a monad comprehension.
Morel's compute clause already uses monoids (admittedly without all of the knobs to choose your own zero element, or fold or rollup functions, but at least you can replace sum in the above example with any function of type α list → α), but we should have syntax for a monoid comprehension without an intermediate list.
We propose compute without group as that syntax:
# Proposed syntax
= from e in scott.emp compute sum of e.sal;
val it = 29025.0 : real
(*) if the monoid is of type "unit list -> 'a" you can omit the "of"
= from e in scott.emp compute count;
val it = 14 : int
(*) when there are two or more aggregates, the result is a record
= from e in scott.emp compute sum of e.sal, count;
val it = {count=14,sum=29025.0} : {count:int, sum:real}
(*) the degenerate case of zero aggregates always returns unit, the empty record
= from e in scott.emp compute;
val it = () : unit
(*) apply user-defined monoid "and_agg"
= from e in scott.emp compute and_agg of e.is_manager;
val it = false : bool
The compute must be the last clause in the from. (After the compute, you have folded the list to a single element, so a where, yield, order, group or second compute doesn't make sense.) The following is illegal:
from e in scott.emp
compute s = sum of e.sal, c = count
yield s + c
You'd write instead:
let
val {s, c} = from e in scott.emp compute s = sum of e.sal, c = count
in
s + c
end;
The text was updated successfully, but these errors were encountered:
Today a
from ... group ... [compute ...]
query returns a list. If the group key is empty (i.e.group
is immediately followed bycompute
, orgroup
marks the end of thefrom
expression) then the list will have one element. You can useonly
(which was added in #62):But it is rather circuitous to first build a list with a single element, and then strip away the list. We just wanted to aggregate the elements.
In functional programming parlance, we want to fold the elements. A type that knows how to fold elements into one is called a monoid. SQL aggregate functions (e.g.
SUM
,COUNT
,MIN
,MAX
) are generally monoids. So are the boolean operationsAND
,OR
andXOR
. In Comprehending Monoids with Class, Perreaux makes the case that a monoid comprehension is more powerful and general than a monad comprehension.Morel's
compute
clause already uses monoids (admittedly without all of the knobs to choose your own zero element, or fold or rollup functions, but at least you can replacesum
in the above example with any function of type α list → α), but we should have syntax for a monoid comprehension without an intermediate list.We propose
compute
withoutgroup
as that syntax:The
compute
must be the last clause in thefrom
. (After thecompute
, you have folded the list to a single element, so awhere
,yield
,order
,group
or secondcompute
doesn't make sense.) The following is illegal:You'd write instead:
The text was updated successfully, but these errors were encountered: