Live data from Hacker News

The unreasonable effectiveness of declarative programming

bollu.github.io

21–30 of 128 posts

Re: The unreasonable effectiveness of declarative programming

#21
post #15

Interesting read. Until safari on my iPhone 7 crashed. Could it be a memory leak? Or simply too many animations for my ageing phone to handle?

For me animations mixed with text is bad UX. Would be better with buttons to start the animations when you have read the relevant paragraph.

Basically auto playing anything for me is bad UX.

Re: The unreasonable effectiveness of declarative programming

#23

In Haskell, one can make more general combinators in the following way: type Anim a = (Duration -> a, Maybe Duration) -- Linear interpolation linear :: Anim Duration linear = (id, Nothing) -- Sequencing seq :: Anim a -> Anim b -> Anim (Either a b) seq (f, Nothing) g = (\t -> Left $ f t, Nothing) seq (f, Just df) (g, dg) = (\t -> if t Anim b -> Anim (a, b) par (f, df) (g, dg) = (\t -> (f t, g t), max df dg) -- Constan…

pedantic stuff:

typo here:

  seq (f, Maybe df) (g, dg) t
s/Maybe/Just/

and `par` should be

  par :: Anim a -> Anim b -> Anim (a, b)
  par (f, df) (g, dg) = (\t -> (f t, g t), max  df  dg)
---

i'm not sure about `par` - if my understanding of Anim is right, it'll take the shorter animation over its specified duration. what if it was something like:

  par a@(_, da) b@(_, db) = (ab, max  da  db)
    where ab t = (a `at` t, b `at` t)
  
  
  at :: Anim a -> Duration -> a
  at (f, Nothing) t = f t
  -- freeze when t exceeds dur, i.e. the animation is done
  at (f, Just dur) t = f (min dur t)
might be less elegant but i'd expect the combinator to respect an animation's duration.

or is that not what the duration represents? i.e. is this correct:

  stretch :: Float -> Anim a -> Anim a
  stretch factor (f, dur) = (\t -> f (t / factor), (factor *)  dur)

Re: The unreasonable effectiveness of declarative programming

#24
post #23

In Haskell, one can make more general combinators in the following way: type Anim a = (Duration -> a, Maybe Duration) -- Linear interpolation linear :: Anim Duration linear = (id, Nothing) -- Sequencing seq :: Anim a -> Anim b -> Anim (Either a b) seq (f, Nothing) g = (\t -> Left $ f t, Nothing) seq (f, Just df) (g, dg) = (\t -> if t Anim b -> Anim (a, b) par (f, df) (g, dg) = (\t -> (f t, g t), max df dg) -- Constan…

pedantic stuff: typo here: seq (f, Maybe df) (g, dg) t s/Maybe/Just/ and `par` should be par :: Anim a -> Anim b -> Anim (a, b) par (f, df) (g, dg) = (\t -> (f t, g t), max df dg) --- i'm not sure about `par` - if my understanding of Anim is right, it'll take the shorter animation over its specified duration. what if it was something like: par a@(_, da) b@(_, db) = (ab, max da db) where ab t = (a `at` t, b `at` t) at…

Thanks. I should have just clarified that I wanted to communicate the idea. I didn't expect to get it right first try.

Maybe I'll try and make a small library of it if there isn't already. I've never posted something on Hackage.

Re: The unreasonable effectiveness of declarative programming

#25
post #23

In Haskell, one can make more general combinators in the following way: type Anim a = (Duration -> a, Maybe Duration) -- Linear interpolation linear :: Anim Duration linear = (id, Nothing) -- Sequencing seq :: Anim a -> Anim b -> Anim (Either a b) seq (f, Nothing) g = (\t -> Left $ f t, Nothing) seq (f, Just df) (g, dg) = (\t -> if t Anim b -> Anim (a, b) par (f, df) (g, dg) = (\t -> (f t, g t), max df dg) -- Constan…

pedantic stuff: typo here: seq (f, Maybe df) (g, dg) t s/Maybe/Just/ and `par` should be par :: Anim a -> Anim b -> Anim (a, b) par (f, df) (g, dg) = (\t -> (f t, g t), max df dg) --- i'm not sure about `par` - if my understanding of Anim is right, it'll take the shorter animation over its specified duration. what if it was something like: par a@(_, da) b@(_, db) = (ab, max da db) where ab t = (a `at` t, b `at` t) at…

Replying to your edit:

As I was writing it my headspace was that the duration was for seq to know when to switch. I wasn't really thinking about stopping the animation too.

(I also notices that my seq is wrong. The subsequent animation should start at the beginning, so it should be `g (t - df)`, not `g t`

I believe you are correct. Your implementation is more at the heart of what I wanted to show. . The main point I wanted to get across was the interface itself.

Re: The unreasonable effectiveness of declarative programming

#26
post #20

Interestingly, if you watch the Erlang: The Movie ( https://www.youtube.com/watch?v=BXmOlCy0oBM ) they use the term 'declarative programming' to refer to what we would now call 'functional programming'. It's an interesting way of thinking about it - these sort of declarative interfaces are very simple in languages with first class function support.

C has first-class functions support, but I don't think it's very easy to define such interfaces in C. Closures and automatic memory management seem to be the "magic dust" that makes this nice to use, first-class functions are necessary but not sufficient.

Re: The unreasonable effectiveness of declarative programming

#27
post #2

I wrote this to show off how to write a compact and powerful animation library. It turned out to be a nice case study in declarative programming as I wrote it! I'd love feedback on the API design, website design, and content as I'm trying to actively improve in all of these areas.

Not that I want to disparage as the library looks neat and clear, but is that what declarative means in 2020 ? The code looks like mainly a builder pattern for an animation datastructure. I've always heard declarative as a sort of synonym to programs defined in terms of equational reasoning such as Lustre for instance - a rule of thumb to separate declarative languages from imperative languages is that in declarative…

there’s a lot of different perspectives on what declarative actually means but in my view it means creating a description of what you want rather than how you want it done. in that sense I think the article qualifies. what you have above is also declarative in the sense that you are describing rules, not how to solve for them. i believe this is kind of declarative is ‘constraint programming’ and also qualifies.

Re: The unreasonable effectiveness of declarative programming

#28
post #19

Back in the day when I was making videogames ( http://www.mysterystudio.com ), I implemented something similar for my framework. Most of the framework was declarative. There were Sprite objects that had an associated Image and a position (among other things). The onUpdate(dt) method of the "screen" didn't explicitly draw things on the screen, it only updated positions and other attributes of the Sprites, and the rend…

My friends and I love playing "Murder, She Wrote" on a big TV screen during downtime at LAN parties. We streamed it on Twitch for a while. We're big fans, great work!

OMG, seriously? You made my day Try the two Sherlock games if you can get them somewhere - these have a special place in my heart :)

Re: The unreasonable effectiveness of declarative programming

#29
Unsolicited code review regarding code readability:

If you write a comment saying x is y. Then rename x to be y. The comment adds a layer of abstraction. Now every time you encounter x you refer to the table of abstractions to get to y.

In a similar way the library has shortened function names. This is another layer of abstraction so you need to decompress the shortened function name once again.

Re: The unreasonable effectiveness of declarative programming

#30
If you want to show off how simple your API is then I can think of several things that would improve clarity:

1. Don't use parentheses in comments. They make things more visually confusing when javascript imposes enough syntactic clutter as it is.

2. What's with /* */ ? Doesn't js allow keyword arguments?

3. Your method names are probably a little short for my taste. I'd be happier with sequence() and parallel() instead of seq() and par(). Par especially seems a little too obscure when first encountering it.

4. "cx = location | cr = radius" - why not allow both forms? - or just the clearer one rather than the shorter one.

Post reply on HN