Closed chshersh closed 6 years ago
Okay, I tried to check whether my idea work or not. Seems like it's working. So you can start from this:
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}
module Time.Formatting
( Series (..)
) where
import Time.Rational (Rat)
import Time.Units (Time)
class Series (units :: [Rat]) where
seriesF :: Time unit -> String
instance Series ('[] :: [Rat]) where
seriesF _ = ""
instance Series (unit ': units :: [Rat]) where
seriesF _ = "smth"
If you call it from REPl, you can see this:
ghci> seriesF @'[MinuteUnit] (sec 3)
"smth"
ghci> seriesF @'[] (sec 3)
""
So the idea is to change this instance:
instance Series (unit ': units :: [Rat]) where
seriesF _ = "smth"
What we need to do is:
Time unit
to unit
from type (probably, type variable names can be changed).floorUnit
and format current unit with unit name.seriesF
recursively. This probably requires to add Series
constraint to units
list.seriesF @'[Second, Minute]
instead of seriesF @'[SecondUnit, MinuteUnit]
(not sure if it's possible or not).It seems to me that this instance should look very similar to this instance of Show
for heterogeneous lists:
It would be good to have some formatting function which can format time units per unit type. For example, if you have
1 day and 1500 ms)
this should be formatted as1d1s500ms
.This can be helpful for something like YouTrack time formatting.
Since we don't know the biggest unit for given
Time unit
the only way to implement this is as I can see: tryFortnightUnit
, then tryWeekUnit
then tryDayUnit
and so on. When we try unit, we're callingfloor
function. And we should try untilt == floor t
.The only problem is fractions. Like
2 % 7
. I propose to format something like2/7ms
as285mcs714ns
.The nicest API is to give explicitly list of units as a type to formatting function. Something like this:
should give formatting for YouTrack like this one:
2d18h40m
But I need to think how to implement such behavior...