var example: [1 << 8]usize = @splat(0);
for (&example, 0..) |*num, int| num.* = int;
This is not more work than what you'd do in a dynamically typed language. tick :: Monad m => m Clock.Present
zero :: Clock.Duration
seconds :: Uint -> Clock.Duration
minutes :: Uint -> Clock.Duration
hours :: Uint -> Clock.Duration
add :: Clock.Duration -> Clock.Present -> Clock.Future
sub :: Clock.Duration -> Clock.Present -> Clock.Past
is :: Clock.Duration -> Clock.Duration -> Bool
until :: Clock.Future -> Clock.Present -> Clock.Duration
since :: Clock.Past -> Clock.Present -> Clock.Duration
timestamp :: Clock.Present -> Clock.Past
compare :: Clock.Present -> Clock.Foreign.Present -> Order
data Order = Ahead Clock.Duration | Equal | Behind Clock.Duration
From the above you can tell what each function should do without looking at the implementation and you can probably write tests for each. Here the interface guides you to handle time in a safer way and tells a story `event = add (hours 5) present` where you cannot mix the wrong type of data ``until event `is` zero``. This is actual code that I've used in a production environment as it saves the team from shooting themselves in the foot with passing a `Clock.Duration` where a `Clock.Present` or `Clock.Future` should have been. Without a static type system you'd likely end up with a mistake mixing those integers up and not having enough test coverage to capture it as the space you must test is much larger than when you've constrained it to a smaller set within the bounds of the backing integer of the above.
I never had a subscription and locking features which could be run locally on the device behind a service is rather annoying.
And yes, those issues were worse after the a firmware update.