Polymorphic existentials

We already have a proposal Packed Existentials , but it has very limited use.

I propose an ALTERNATIVE: to add Polymorphic existentials (and Monomorphic existentials)

Quantifiers:
∀a : forall a. a is a monomorphic Set
∃b : exists b. b is a polymorphic Set
☥c : forunique c. c is a monomorphic element of Set

Constraint operations of Sets
a ≡ b : a =~ b Sets a and b are equal
a ⊆ b : a <~ b Set a is a subset of b
a ∈ b : a !~ b a is an element of b
a | b : a | b Union of Sets a and b
a \ b : a \ b Remove set b from a set

Some axioms and rules
For forunique:

1) let  forunique a.  then  a ~ a

For forall and exists:

1) let  exists a.  then  a =~ a
2) let  exists a b.  if  a =~ b  then  b =~ a 
3) let  exists a.  then  a <~ a
4) let  exists a b c.  if  a <~ b, b <~ c  then  a <~ c
5) let  exists a b.  then  a | b =~ b | a
6) let  exists a b.  then  a <~ a | b
7) let  exists a b.  then  a | b \ b <~ a

Narrow Type < Wide Type

1) (forunique a: a) < (exists b. forunique a. a !~ b. b)
2) (forunique a: a) < (forall b. forunique a. a !~ b. b)

3) (forall a: a) <  (exists b. forall a. a <~ b => b)
4) (forall a: a) >! (forall a. forunique b. b !~ a. a)

5) (exists a: a) <  (exists b. exists a. a <~ b => b)
6) (exists a: a) >! (exists a. forunique b. b !~ a => b)

All real data, which consists forall a is simplified to some specific Int, String, ....
Same with real data exists a: a is simplified to some specific exists a. forunique b. b !~ a => b.

But not all existential data is reducible.

  • Irreducible Compound-valued (self-recursive type), like exists a. [a]
  • Irreducible Compound-argument types, like exists a. (a, a)

Some examples:

fromEither :: forall a b. exists c. c =~ a | b => Either a b -> c
fromEither (Left a)  = a
fromEither (Right b) = b

2-ranked forall

data exist a. Box a = forall b. b =~ a => MkBox b

fromBox :: exists a. Box a -> a
fromBox (MkBox a) = a

multitypedList :: exists a. [Box a]
multitypedList :: exists a. a =~ String | Int | Maybe Int  => [Box a]
multitypedList = [MkBox "a", MkBox 1, MkBox (Just 5)]

multitypedList :: forall c. [Box c]
multitypedList :: forunique b. [Box b]
multitypedList :: [Box String]
multitypedList2 = [MkBox "a", MkBox "bb", MkBox "ccc"]

Class as named existential function (it is not part of proposal), just for clarification:

class Eq a where
    (==) :: Eq a => a -> a -> Bool

instance Eq Int where 

instance Eq String where 

-- pseudo-haskell
type exists Eq

(==) :: forall a. a =~ Eq => a -> a -> Bool

override type exists Eq = Eq | Int
(==) :: Int !~ Eq => Int -> Int -> Bool

override type exists Eq = Eq | String
(==) :: String !~ Eq => String -> String -> Bool

and depended classes:

class C a b | a -> b where

-- pseudo-haskell
class C a (foruniuqe b. b) where

Promoted Sum-Type

Promoted Sum-Type is … existential!

data Nat = Zero | Succ Nat

-- promoted, pseudo-haskell
data exists 'Nat = 'Zero | 'Succ 'Nat

About Vectors:

type Vec :: Nat -> Type -> Type
data Vec n a where
  VNil :: Vec Zero a
  (:>) :: forall a n. a -> Vec n a -> Vec (Succ n) a

vecUnique :: forall a. forunique m. exists n. n =~ Nat, m !~ Nat => Vec n a -> Vec m a
vecUnique x = x

filter :: exists m. forall a n. n =~ Nat, m =~ Nat => (a -> Bool) -> Vec n a -> Vec m a
filter p VNil = VNil
filter p (x :> xs)
  | p x       = x :> (vecUnique (filter p xs))
  | otherwise = filter p xs 

fromList :: forall a. exists n. n ~ Nat => [a] -> Vec n a
fromList []     = VNil               
fromList (x:xs) = x :> (vecUnique (fromList xs)) 

Could you elaborate on the “limited use” and how your approach improves it?

Shouldn’t that be:

fromList :: forall a. [a] -> exists n. n ~ Nat => Vec n a

Because you only know the n after you’ve looked at the list. Or how would you propose this is translated to Core?

Yes, you are right.

vecUnique :: forall a. exists n. n =~ Nat => Vec n a -> forunique m. m !~ Nat => Vec m a
vecUnique x = x

filter :: forall a n. n =~ Nat => (a -> Bool) -> Vec n a -> exists m. m =~ Nat => Vec m a
filter p VNil = VNil
filter p (x :> xs)
  | p x       = x :> (vecUnique (filter p xs))
  | otherwise = filter p xs 

fromList :: forall a. [a] -> exists n. n ~ Nat => Vec n a
fromList []     = VNil               
fromList (x:xs) = x :> (vecUnique (fromList xs))