haskell-fsrs-7.1.0: src/FSRS/Types.hs
{-# LANGUAGE DerivingStrategies #-}
-- | The vocabulary shared by the whole package: the four grades a reviewer can
-- give a card, and the two-variable memory state FSRS tracks for it.
module FSRS.Types
( -- * Ratings
Rating (..)
, allRatings
, ratingToInt
, ratingFromInt
-- * Memory state
, MemoryState (..)
-- * Type synonyms
, Stability
, Difficulty
, Retrievability
, Days
) where
-- | How well the card was recalled. The 'Enum' instance counts from @0@; the
-- FSRS papers and reference implementations number the ratings from @1@, which
-- is what 'ratingToInt' gives you.
data Rating
= Again
| Hard
| Good
| Easy
deriving stock (Eq, Ord, Show, Read, Enum, Bounded)
-- | Every rating, from 'Again' to 'Easy'.
allRatings :: [Rating]
allRatings = [minBound .. maxBound]
-- | The rating as FSRS numbers it: @1@ for 'Again' through @4@ for 'Easy'.
ratingToInt :: Rating -> Int
ratingToInt r = fromEnum r + 1
-- | Inverse of 'ratingToInt'. 'Nothing' outside @1..4@.
ratingFromInt :: Int -> Maybe Rating
ratingFromInt n
| n >= 1 && n <= 4 = Just (toEnum (n - 1))
| otherwise = Nothing
-- | Memory half-life in days: the larger it is, the slower the card is
-- forgotten. In FSRS-7 stability is a genuine continuous quantity — sub-day
-- values are meaningful and are what the model uses for same-day reviews.
type Stability = Double
-- | How hard the card is for this reviewer, on a @[1, 10]@ scale.
type Difficulty = Double
-- | Probability of recall. FSRS-7 squeezes it into @[1e-5, 1 - 1e-5]@ so that
-- neither it nor its logarithm can saturate, so a card reviewed a moment ago
-- has a retrievability just short of @1@ rather than exactly @1@.
type Retrievability = Double
-- | A duration in days. Fractional values are meaningful throughout FSRS-7:
-- ten minutes is @10 / 1440@.
type Days = Double
-- | Everything FSRS remembers about a card.
--
-- FSRS-7 tracks /two/ memory traces rather than one. Both are stabilities in
-- the same units; they differ only in how fast they decay and in which weights
-- update them.
--
-- * 'memoryStability' is the slow trace — the durable memory, and the one a
-- scheduler turns into an interval.
-- * 'memoryStabilityFast' is the fast trace, which carries the short-lived
-- boost a review gives you. It is what makes same-day reviews behave
-- differently from spaced ones, and it replaces the elapsed-time blend
-- between a long- and a short-term update that earlier drafts of FSRS-7
-- used.
--
-- The forgetting curve is a mixture of the two, so 'retrievability' needs a
-- whole 'MemoryState' — including the difficulty, which in FSRS-7 shapes the
-- curve as well.
data MemoryState = MemoryState
{ memoryStability :: !Stability
, memoryDifficulty :: !Difficulty
, memoryStabilityFast :: !Stability
}
deriving stock (Eq, Ord, Show, Read)