{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LinearTypes #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Unsafe.Linear
(
coerce,
toLinear,
toLinear2,
toLinear3,
toLinearN,
ToLinearN (..),
)
where
import Data.Kind (Constraint)
import Data.Type.Equality (type (~~))
import GHC.Exts (RuntimeRep (..), TYPE)
import GHC.TypeNats
import Unsafe.Coerce (UnsafeEquality (..), unsafeEqualityProof)
coerce :: forall a b. a %1 -> b
coerce :: forall a b. a %1 -> b
coerce a
a =
case forall {k} (a :: k) (b :: k). UnsafeEquality a b
forall a b. UnsafeEquality a b
unsafeEqualityProof @a @b of
UnsafeEquality a b
UnsafeRefl -> a
b
a
{-# INLINE coerce #-}
toLinear ::
forall
(r1 :: RuntimeRep)
(r2 :: RuntimeRep)
(a :: TYPE r1)
(b :: TYPE r2)
p
x.
(a %p -> b) %1 ->
(a %x -> b)
toLinear :: forall a b (p :: Multiplicity) (x :: Multiplicity).
(a %p -> b) %1 -> a %x -> b
toLinear a %p -> b
f = case forall {k} (a :: k) (b :: k). UnsafeEquality a b
forall (a :: Multiplicity) (b :: Multiplicity). UnsafeEquality a b
unsafeEqualityProof @p @x of
UnsafeEquality p x
UnsafeRefl -> a %p -> b
a %x -> b
f
toLinear2 ::
forall
(r1 :: RuntimeRep)
(r2 :: RuntimeRep)
(r3 :: RuntimeRep)
(a :: TYPE r1)
(b :: TYPE r2)
(c :: TYPE r3)
p
q
x
y.
(a %p -> b %q -> c) %1 ->
(a %x -> b %y -> c)
toLinear2 :: forall a b c (p :: Multiplicity) (q :: Multiplicity)
(x :: Multiplicity) (y :: Multiplicity).
(a %p -> b %q -> c) %1 -> a %x -> b %y -> c
toLinear2 a %p -> b %q -> c
f = case forall {k} (a :: k) (b :: k). UnsafeEquality a b
forall (a :: (Multiplicity, Multiplicity))
(b :: (Multiplicity, Multiplicity)).
UnsafeEquality a b
unsafeEqualityProof @'(p, q) @'(x, y) of
UnsafeEquality '(p, q) '(x, y)
UnsafeRefl -> a %p -> b %q -> c
a %x -> b %y -> c
f
toLinear3 ::
forall
(r1 :: RuntimeRep)
(r2 :: RuntimeRep)
(r3 :: RuntimeRep)
(r4 :: RuntimeRep)
(a :: TYPE r1)
(b :: TYPE r2)
(c :: TYPE r3)
(d :: TYPE r4)
p
q
r
x
y
z.
(a %p -> b %q -> c %r -> d) %1 ->
(a %x -> b %y -> c %z -> d)
toLinear3 :: forall a b c d (p :: Multiplicity) (q :: Multiplicity)
(r :: Multiplicity) (x :: Multiplicity) (y :: Multiplicity)
(z :: Multiplicity).
(a %p -> b %q -> c %r -> d) %1 -> a %x -> b %y -> c %z -> d
toLinear3 a %p -> b %q -> c %r -> d
f = case forall {k} (a :: k) (b :: k). UnsafeEquality a b
forall (a :: (Multiplicity, Multiplicity, Multiplicity))
(b :: (Multiplicity, Multiplicity, Multiplicity)).
UnsafeEquality a b
unsafeEqualityProof @'(p, q, r) @'(x, y, z) of
UnsafeEquality '(p, q, r) '(x, y, z)
UnsafeRefl -> a %p -> b %q -> c %r -> d
a %x -> b %y -> c %z -> d
f
toLinearN :: forall n f g. ToLinearN n f g => f %1 -> g
toLinearN :: forall (n :: Nat) f g. ToLinearN n f g => f %1 -> g
toLinearN f
f = case forall (n :: Nat) f g. ToLinearN n f g => UnsafeEquality f g
forall (n :: Nat) f g. ToLinearN n f g => UnsafeEquality f g
unsafeLinearityProofN @n @f @g of
UnsafeEquality f g
UnsafeRefl -> f
g
f
type ToLinearN :: forall {rep :: RuntimeRep}. Nat -> TYPE rep -> TYPE rep -> Constraint
class ToLinearN n f g where
unsafeLinearityProofN :: UnsafeEquality f g
instance (ToLinearN' ni f g, ni ~ ToINat n) => ToLinearN n f g where
unsafeLinearityProofN :: UnsafeEquality f g
unsafeLinearityProofN = forall (arrs :: INat) f g.
ToLinearN' arrs f g =>
UnsafeEquality f g
forall (arrs :: INat) f g.
ToLinearN' arrs f g =>
UnsafeEquality f g
prf @ni
data INat = Z | S INat
type ToINat :: Nat -> INat
type family ToINat n where
ToINat 0 = 'Z
ToINat n = 'S (ToINat (n - 1))
type ToLinearN' :: forall {rep :: RuntimeRep}. INat -> TYPE rep -> TYPE rep -> Constraint
class ToLinearN' arrs f g where
prf :: UnsafeEquality f g
instance a ~ b => ToLinearN' 'Z (a :: TYPE rep) (b :: TYPE rep) where
prf :: UnsafeEquality a b
prf = UnsafeEquality a b
forall {k} (a :: k). UnsafeEquality a a
UnsafeRefl
instance
( ToLinearN' k fb gb,
x ~~ ((a :: TYPE repa) %p -> (fb :: TYPE repb)),
y ~~ (a %q -> (gb :: TYPE repb))
) =>
ToLinearN' ('S k) (x :: TYPE rep) (y :: TYPE rep)
where
prf :: UnsafeEquality x y
prf = case forall (arrs :: INat) f g.
ToLinearN' arrs f g =>
UnsafeEquality f g
forall (arrs :: INat) (f :: TYPE repb) (g :: TYPE repb).
ToLinearN' arrs f g =>
UnsafeEquality f g
prf @k @fb @gb of
UnsafeEquality fb gb
UnsafeRefl -> case forall {k} (a :: k) (b :: k). UnsafeEquality a b
forall (a :: Multiplicity) (b :: Multiplicity). UnsafeEquality a b
unsafeEqualityProof @p @q of
UnsafeEquality p q
UnsafeRefl -> UnsafeEquality x y
forall {k} (a :: k). UnsafeEquality a a
UnsafeRefl