fork download
  1. {-# LANGUAGE GADTs, KindSignatures, DataKinds #-}
  2.  
  3. import Prelude hiding (Bounded, succ)
  4. import Control.Applicative
  5. import Data.Maybe
  6.  
  7. data Nat = Z | S Nat
  8.  
  9. data Bounded (n :: Nat) where
  10. BZ :: Bounded n
  11. BS :: Bounded n -> Bounded (S n)
  12.  
  13. instance Show (Bounded n) where
  14. show BZ = "BZ"
  15. show (BS bn) = "BS (" ++ show bn ++ ")"
  16.  
  17. instance Eq (Bounded n) where
  18. BZ == BZ = True
  19. BS bn == BS bm = bn == bm
  20. _ == _ = False
  21.  
  22. zero :: Bounded (S (S Z))
  23. zero = BZ
  24.  
  25. one :: Bounded (S (S Z))
  26. one = BS BZ
  27.  
  28. two :: Bounded (S (S Z))
  29. two = BS (BS BZ)
  30.  
  31. data Natty (n :: Nat) where
  32. Zy :: Natty Z
  33. Sy :: Natty n -> Natty (S n)
  34.  
  35. class NATTY (n :: Nat) where
  36. natty :: Natty n
  37.  
  38. instance NATTY Z where
  39. natty = Zy
  40.  
  41. instance NATTY n => NATTY (S n) where
  42. natty = Sy natty
  43.  
  44. succ :: NATTY n => Bounded n -> Bounded n
  45. succ bn = fromMaybe BZ $ go natty bn where
  46. go :: Natty n -> Bounded n -> Maybe (Bounded n)
  47. go Zy BZ = Nothing
  48. go (Sy ny) BZ = Just (BS BZ)
  49. go (Sy ny) (BS bn) = BS <$> go ny bn
  50.  
  51. main = do
  52. print $ succ zero == zero -- False
  53. print $ succ zero == one -- True
  54. print $ succ one == two -- True
  55. print $ succ two == zero -- True
Success #stdin #stdout 0s 4548KB
stdin
Standard input is empty
stdout
False
True
True
True