4 ms·
In Haskell, one can make more general combinators in the following way: type Anim a = (Duration -> a, Maybe Duration) -- Linear interpolation linear
by reuben364 6y ago
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 < df
then Left $ f t
else Right $ g t
, df + dg)
-- Parallelism
par :: Anim a -> Anim b -> Anim (a, b)
par (f, df) (g, dg) = (\t -> (f t, g t), max df dg)
-- Constant
pure :: a -> Anim a
pure a = (const a, Nothing)
-- EDIT: forgot delay
delay :: Duration -> Anim ()
delay d = (const (), d)
I know there's an Applicative in there, but I'm not sure where else this lies in the typeclass hierarchy.
EDIT: More fixes
EDIT: I should really test in GHCI before I post these things. But I'm lazy.
- quickthrower2 6y agoThat looks neat. Making me fall in love with Haskell again which I want to avoid as I can’t use it at work ;) You could add a monoid instance which would be useful (for one example) if the animation produces a matrix transform then you could combine two animations that produce transforms. For example a rotation and a move. I’m sure there are other good monoid animations. Strings would be a simple example I guess.
- uryga 6y agopedantic 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)
- reuben364 6y agoThanks. 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.
- reuben364 6y agoReplying 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.
- uryga 6y agoit's a nice idea, i was just in a nitpicky mood :)
- Lemmih 6y agoThis is almost exactly how reanimate generates animations with Haskell: https://github.com/Lemmih/reanimate https://github.com/Lemmih/reanimate Animations are frames over time and can be composed using 'seqA' and 'parA' combinators.
- reuben364 6y agoOne thing I realized that seq'ing too many things might be bad for performance. As I understand it, foldr1 (\x y -> ((x `par` delay 1) `seq` y)) $ map pure [1..] Would require more and more comparisons over time. Is there some sort of codensity like trick that you can do? Or is this something the user of the library would worry about if it came to that. Or just have a redundant API.
- tonetheman 6y agoI am literally too dumb to know what you typed... and then all of the following comments. It is like you are speaking in Martian or something. Haskell is effectively impenetrable to me.
- 6510 6y agoI dunno, I prefer to call it too practical. Lets just do terrestrial programming. Something like this? @keyframes ball{ 0%{ left:50px; top:100px;width:0px; height:0px } 10%{ left:50px; top:90px; width:20px; height:20px } 20%{ left:50px; top:90px; width:20px; height:20px } 30%{ left:300px;top:50px; width:100px;height:100px} 50%{ left:300px;top:50px; width:100px;height:100px} 60%{ left:200px;top:50px; width:100px;height:100px} 90%{ left:250px;top:100px;width:0px; height:0px } 100%{left:50px; top:100px;width:0px; height:0px } } https://jsfiddle.net/gaby_de_wilde/eoj875qr/ https://jsfiddle.net/gaby_de_wilde/eoj875qr/
- reuben364 6y agoI thought so too, but Haskell was an object of adoration and envy for me long enough for me to become hooked. If Martians visited Earth, surely you'd want to learn their language. :)