{-# OPTIONS_HADDOCK hide #-} {-# LANGUAGE NoImplicitPrelude #-} module Imj.Graphics.Class.DiscreteDistance ( DiscreteDistance(..) , Successive(..) ) where import Imj.Prelude import Data.List( length ) -- | Wrapper on a list, to represents successive waypoints. newtype Successive a = Successive [a] deriving(Show) {- | Instances should satisfy: \( \forall (\, from, to)\, \in v, \) * 'distance' @from to@ >= 0 * 'distance' @from to@ can be different from 'distance' @to from@, to provide different forward and backward interpolations (or morphings). -} class DiscreteDistance v where -- | Distance between two 'DiscreteDistance's. distance :: v -- ^ first value -> v -- ^ last value -> Int -- ^ the number of steps (including first and last) to go from first to last -- | Distance between n successive 'DiscreteDistance's. distanceSuccessive :: Successive v -> Int distanceSuccessive (Successive []) = error "empty successive" distanceSuccessive (Successive l@(_:_)) = succ $ sum $ zipWith (\a b -> pred $ distance a b) l $ tail l -- | Naïve interpolation. instance DiscreteDistance Int where distance i i' = 1 + abs (i-i') -- | Interpolation between 2 lists, occuring in parallel between same-index elements. -- Prerequisite : lists have the same lengths. -- -- For an interpolation that occurs sequentially between same-index elements, -- use SequentiallyInterpolatedList. instance (DiscreteDistance a) => DiscreteDistance ([] a) where distance [] _ = 1 distance _ [] = 1 distance l l' = maximum $ zipWith distance l $ assert (length l == length l') l'