Skip to content

Instantly share code, notes, and snippets.

@kosmikus
Created May 31, 2017 14:48
Show Gist options
  • Save kosmikus/ea4ca9a7c5ab9e251d49b2a5f919ed5f to your computer and use it in GitHub Desktop.
Save kosmikus/ea4ca9a7c5ab9e251d49b2a5f919ed5f to your computer and use it in GitHub Desktop.
{-# LANGUAGE DataKinds, GADTs, PatternSynonyms, PolyKinds, ScopedTypeVariables, TypeFamilies, ViewPatterns #-}
module SingNat where
import Unsafe.Coerce
data Nat = Z | S Nat
data family Sing (a :: k)
newtype instance Sing (a :: Nat) = SingNat Int
data IsSingNat (a :: Nat) where
IsSZ :: IsSingNat Z
IsSS :: Sing n -> IsSingNat (S n)
isSingNat :: Sing n -> IsSingNat n
isSingNat (SingNat 0) = unsafeCoerce IsSZ
isSingNat (SingNat n) = unsafeCoerce IsSS (SingNat (n - 1))
pattern SZ :: forall (n :: Nat) . () => (n ~ Z) => Sing n
pattern SZ <- (isSingNat -> IsSZ)
where
SZ = SingNat 0
pattern SS :: forall (n :: Nat) . () => forall (n' :: Nat) . (n ~ S n') => Sing n' -> Sing n
pattern SS n <- (isSingNat -> IsSS n)
where
SS (SingNat n) = SingNat (n + 1)
~
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment