Skip to content

Instantly share code, notes, and snippets.

@bkase
Created October 6, 2017 08:34
Show Gist options
  • Save bkase/16b2de2c3bcae1b89287f402daea86ba to your computer and use it in GitHub Desktop.
Save bkase/16b2de2c3bcae1b89287f402daea86ba to your computer and use it in GitHub Desktop.
Rough Sketch Functional Animations
// SUPER ROUGH ideas about distributive property on Animations
// This is the "current relative time as input" rather than the "0 to 1 as input" (unit) version of the animation
// this has flaws, but simple to show (or not) the distributive property of sequence and parallel
infix operator <>: AdditionPrecedence
protocol Semigroup {
static func <>(lhs: Self, rhs: Self) -> Self
}
indirect enum FreeSemigroup<A>: Semigroup {
case One(A)
case More(A, FreeSemigroup<A>)
}
// The seq/paralell forms an identity-less tropical-like semiring ( https://github.com/paf31/purescript-tropical/blob/master/src/Data/Semiring/Tropical.purs )
// over the durations (so distributive property holds there)
// Let A, B, C be animations
// Want to show: A * (B + C)
// Starting from: A * B + A * C
// A : B + A : C <-- (by definition of * (the colon just means ternary it))
// A : B <> A : C <-- (by definition of +; pointwise a semigroup)
// (A <> A) : (B <> C) <-- (I think <> distributes over the ternary, but I might be too tired)
// A : (B <> C) <-- this step is where it breaks down, but it makes intuitive sense just thinking about animations in the abstract:
// Running an animation in parallel with itself should no-op... Not sure what the impl would need to be for parallel,
// but I think this is the problem.
// A : (B + C) <-- by definition of +
// A * (B + C) <-- by definition of *
// qed
struct Animation<A: Semigroup> {
let duration: Double
let run: (Double) -> A
static func * (lhs: Animation, rhs: Animation) -> Animation {
return Animation(duration: lhs.duration + rhs.duration) { t in
(t < lhs.duration) ? lhs.run(t) : rhs.run(t)
}
}
// Animation<FreeSemigroup<A>> recovers the power of the tupling of the sequence
// (mostly sort of). I think the semigroup constraint is more powerful than the tupling.
static func + (lhs: Animation, rhs: Animation) -> Animation {
return Animation(duration: max(lhs.duration, rhs.duration)) { t in
lhs.run(t) <> rhs.run(t)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment