fork download
  1. {-# LANGUAGE RankNTypes #-}
  2. {-# LANGUAGE TypeFamilies #-}
  3.  
  4. module Phantom where
  5.  
  6. data Zero
  7. data Succ n
  8.  
  9. type One = Succ Zero
  10. type Two = Succ One
  11. type Four = Succ (Succ Two )
  12. type Six = Succ (Succ Four)
  13. type Eight = Succ (Succ Six )
  14.  
  15. class Nat n where
  16. toInt :: n -> Int
  17. instance Nat Zero where
  18. toInt _ = 0
  19. instance (Nat n) => Nat (Succ n) where
  20. toInt _ = 1 + toInt (undefined :: n)
  21.  
  22. newtype Pointer n = MkPointer Int
  23. newtype Offset n = MkOffset Int
  24.  
  25. multiple :: forall n. (Nat n) => Int -> Offset n
  26. multiple i = MkOffset (i * toInt (undefined :: n))
  27.  
  28. add :: Pointer m -> Offset n -> Pointer (GCD Zero m n)
  29. add (MkPointer x) (MkOffset y) = MkPointer (x + y)
  30.  
  31. fetch32 :: (GCD Zero n Four ~ Four) => Pointer n -> IO ()
  32. fetch32 = undefined
  33.  
  34. type family GCD d m n
  35. type instance GCD d Zero Zero = d
  36. type instance GCD d (Succ m) (Succ n) = GCD (Succ d) m n
  37. type instance GCD Zero (Succ m) Zero = Succ m
  38. type instance GCD (Succ d) (Succ m) Zero = GCD One d m
  39. type instance GCD Zero Zero (Succ n) = Succ n
  40. type instance GCD (Succ d) Zero (Succ n) = GCD One d n
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
[1 of 1] Compiling Phantom          ( prog.hs, prog.o )

prog.hs:20:19: error:
    • Could not deduce (Nat n1) arising from a use of ‘toInt’
      from the context: Nat n
        bound by the instance declaration at prog.hs:19:10-32
      The type variable ‘n1’ is ambiguous
      These potential instances exist:
        instance Nat n => Nat (Succ n) -- Defined at prog.hs:19:10
        instance Nat Zero -- Defined at prog.hs:17:10
    • In the second argument of ‘(+)’, namely ‘toInt (undefined :: n)’
      In the expression: 1 + toInt (undefined :: n)
      In an equation for ‘toInt’: toInt _ = 1 + toInt (undefined :: n)
   |
20 |     toInt _ = 1 + toInt (undefined :: n)
   |                   ^^^^^^^^^^^^^^^^^^^^^^

prog.hs:26:28: error:
    • Could not deduce (Nat n0) arising from a use of ‘toInt’
      from the context: Nat n
        bound by the type signature for:
                   multiple :: forall n. Nat n => Int -> Offset n
        at prog.hs:25:1-48
      The type variable ‘n0’ is ambiguous
      These potential instances exist:
        instance Nat n => Nat (Succ n) -- Defined at prog.hs:19:10
        instance Nat Zero -- Defined at prog.hs:17:10
    • In the second argument of ‘(*)’, namely ‘toInt (undefined :: n)’
      In the first argument of ‘MkOffset’, namely
        ‘(i * toInt (undefined :: n))’
      In the expression: MkOffset (i * toInt (undefined :: n))
   |
26 | multiple i = MkOffset (i * toInt (undefined :: n))
   |                            ^^^^^^^^^^^^^^^^^^^^^^
stdout
Standard output is empty