4 ms·
I don't think it makes that much sense w.r.t stream events: 1. most of the analytics/event-stream processing will be done on the backend anyway 2. If you are
by a-saleh 11y ago
I don't think it makes that much sense w.r.t stream events:
1. most of the analytics/event-stream processing will be done on the backend anyway
2. If you are picky enough you can do functional programming in js. Reative.js is decent library for processing streams of events.
What screams to use something more haskell-like, is their example of 'Trys', i.e:
class GraphQuery extends Query {
static parse(object: any): Try<GraphQuery> {
return TimeRange.parse(object.over).flatMap((timeRange: TimeRange) => {
return Filter.parse(object.where).flatMap((filter: Option<Filter>) => {
return GroupBy.parse(object.by).flatMap((groupBy: Option<GroupBy>) => {
return new Success(new GraphQuery(
filter,
groupBy,
timeRange
));
});
});
});
}
}
should look like something like:
parse : Any -> Try GraphQuery
parse object = do
timeRange <- TimeRange.parse object.over
filter <- Filter.parse object.where
groupBy <- GroupBy.parse object.by
return (createGraphQuery filter groupBy timeRange)
(haven't used haskell in quite some time, so maybe I am missing something)
- jiaweihli 11y agoYou're absolutely right! I was hoping someone would point this out, since this is a much cleaner way of writing this code. This is pretty close to how it's done in Scala. For the purposes of this article, we tried to avoid too much syntax sugar to make it more accessible. That aside, I'd love to add something like this to monapt![1]. [1] https://github.com/jiaweihli/monapt https://github.com/jiaweihli/monapt
- roryokane 11y agoHere’s a sketch of some potential syntax to simplify your TypeScript so it’s like that Haskell code. class GraphQuery extends Query { static parse(object: any): Try<GraphQuery> { return TimeRange.parse(object.over) .combinedWith(() => Filter.parse(object.where) ) .combinedWith(() => GroupBy.parse(object.by) ) .withCombinedValues((timeRange, filter, groupBy) => { return new Success(new GraphQuery(filter, groupBy, timeRange)); }); } } In this design, `combinedWith` is a lot like `then` when using promises. It’s a bit more complicated because `then` assumes that arguments are always passed directly from the previous function, so you need special support to store the return value and retrieve them later as arguments. If the type system requires it for some reason, you could add a `.startCombining()` call at the end of the first line within the method, so that `combinedWith` is sure to be possible.
- sremani 11y agoMay be you can funscript? http://funscript.info/ http://funscript.info/ It leverages TypeScript metadata to do typed interop with JavaScript libraries through an F# type provider
- boothead 11y agoYou can build UIs as a left fold over events, just as you can build backend data processing pipelines. In fact it that is the architecture that makes the most sense to me now. I have a little toy framework here that demos these ideas. https://github.com/boothead/oHm https://github.com/boothead/oHm
- jsprogrammer 11y ago>should look like something like: > parse : Any -> Try GraphQuery > parse object = do > timeRange <- TimeRange.parse object.over > filter <- Filter.parse object.where > groupBy <- GroupBy.parse object.by > return (createGraphQuery filter groupBy timeRange) New ECMAScript 2015 Style parse = ({by, over, where}) => { timeRange = TimeRange.parse(over) filter = Filter.parse(where) groupBy = GroupBy.parse(by) return createGraphQuery(filter, groupBy, timeRange) } or parse = ({by, over, where}) => createGraphQuery( Filter.parse(where), GroupBy.parse(by), TimeRange.parse(over)); or parse = ({by, over, where}) => createGraphQuery( Filter(where), GroupBy(by), TimeRange(over)); or parse = ({by, over, where}) => createGraphQuery( Filter(where), GroupBy(by), TimeRange(over) ); or parse = ({by, over, where}) => c(f(where), g(by), t(over)); and, if you're willing to put a front-end on it: parse = ({b, o, w}) => c(f(w), g(b), t(o)); Of course, I have not provided the definitions of `c`, `f`, `g`, or `t`.
- jiaweihli 11y agoThis is slightly different from the original code. The reason for all the flatmapping is to avoid continuation if any of the subparsers fail, and notify the caller that something has failed because of {some exception}. You can avoid excessive nesting/flatmapping with some syntax sugar, but it needs to be sufficiently different from normal declarative code.
- jsprogrammer 11y agoI alluded to that in my last note. :) If you properly define the functions (`c`, `f`, `g`, `t`), you can get the semantics of halted computation on failure. That is essentially what Haskell's `do` notation does.