packages feed

strongweak-0.11.0: src/Strongweak/WeakenN/Internal.hs

{-# LANGUAGE UndecidableInstances #-} -- type family 'Weakened' in constraints
{-# LANGUAGE AllowAmbiguousTypes #-} -- ambiguous intermediate type classes

{- | 'Strongweak.WeakenN.WeakenN' internals.

Just in case. You shouldn't need these, but they might be fun to look at.

__Internal module. Exports may change without warning. Try not to use.__
-}

module Strongweak.WeakenN.Internal where

import Strongweak.Weaken ( Weaken(weaken), type WeakenedN )
import Strongweak.Strengthen
import GHC.TypeNats ( type Natural, type (-) )
import Unsafe.Coerce ( unsafeCoerce )

class WeakenWeakenN (n :: Natural) a where
    weakenWeakenN :: a -> WeakenedN n a

-- | Zero case: return the value as-is.
instance {-# OVERLAPPING #-} WeakenWeakenN 0 a where
    weakenWeakenN = id

-- | Inductive case. @n /= 0@, else this explodes.
instance (Weaken a, WeakenWeakenN (n-1) (Weakened a))
  => WeakenWeakenN n a where
    weakenWeakenN a =
        case weakenWeakenN @(n-1) @(Weakened a) (weaken a) of
          x -> weakenedNRL1 @n @a x

-- | Inverted inductive 'WeakenedN'case.
--
-- @n@ must not be 0.
weakenedNRL1 :: forall n a. WeakenedN (n-1) (Weakened a) -> WeakenedN n a
weakenedNRL1 = unsafeCoerce

class WeakenWeakenN n a => StrengthenWeakenN (n :: Natural) a where
    strengthenWeakenN :: WeakenedN n a -> Either StrengthenFailure' a

instance {-# OVERLAPPING #-} StrengthenWeakenN 0 a where
    strengthenWeakenN = Right

instance (Strengthen a, StrengthenWeakenN (n-1) (Weakened a))
  => StrengthenWeakenN n a where
    strengthenWeakenN a =
        case strengthenWeakenN @(n-1) @(Weakened a) (weakenedNLR1 @n @a a) of
          Left  e  -> Left e
          Right sa -> strengthen sa

-- | Inductive 'WeakenedN'case.
--
-- @n@ must not be 0.
weakenedNLR1 :: forall n a. WeakenedN n a -> WeakenedN (n-1) (Weakened a)
weakenedNLR1 = unsafeCoerce