summaryrefslogtreecommitdiff
path: root/testsuite/tests/simplCore/should_run/T13750a.hs
blob: 7ed72ca241039ef09a8fa4cfd9a29e7354486fea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ViewPatterns #-}
module T13750a where

import Unsafe.Coerce

type family AnyT :: * where {}
type family AnyList :: [*] where {}

newtype NP (xs :: [*]) = NP [AnyT]

data IsNP (xs :: [*]) where
  IsNil  :: IsNP '[]
  IsCons :: x -> NP xs -> IsNP (x ': xs)

isNP :: NP xs -> IsNP xs
isNP (NP xs) =
  if null xs
    then unsafeCoerce IsNil
    else unsafeCoerce (IsCons (head xs) (NP (tail xs)))

pattern Nil :: () => (xs ~ '[]) => NP xs
pattern Nil <- (isNP -> IsNil)
  where
    Nil = NP []

pattern (:*) :: () => (xs' ~ (x ': xs)) => x -> NP xs -> NP xs'
pattern x :* xs <- (isNP -> IsCons x xs)
  where
    x :* NP xs = NP (unsafeCoerce x : xs)
infixr 5 :*

data NS (xs :: [[*]]) = NS !Int (NP AnyList)

data IsNS (xs :: [[*]]) where
  IsZ :: NP x -> IsNS (x ': xs)
  IsS :: NS xs -> IsNS (x ': xs)

isNS :: NS xs -> IsNS xs
isNS (NS i x)
  | i == 0    = unsafeCoerce (IsZ (unsafeCoerce x))
  | otherwise = unsafeCoerce (IsS (NS (i - 1) x))

pattern Z :: () => (xs' ~ (x ': xs)) => NP x -> NS xs'
pattern Z x <- (isNS -> IsZ x)
  where
    Z x = NS 0 (unsafeCoerce x)

pattern S :: () => (xs' ~ (x ': xs)) => NS xs -> NS xs'
pattern S p <- (isNS -> IsS p)