packages feed

type-set-0.1.0.0: src/Data/Type/Set/Internal.hs

{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DataKinds, TypeOperators #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE PolyKinds, UndecidableInstances #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Data.Type.Set.Internal (
	-- * Set
	Set(Nil, (:~)),
	-- * Numbered
	Numbered, numbered,
	-- * Function
	Singleton, Insert, Merge, Map,
	-- * Operator
	(:-), (:+:) ) where

import GHC.TypeLits (Nat, type (<=?))
import Language.Haskell.TH (
	TypeQ, DecsQ, runIO,
	instanceD, cxt, tySynInstD, tySynEqn, conT, appT, litT, numTyLit )
import Data.Kind (Type)
import System.Random (randomRIO)

---------------------------------------------------------------------------

-- * TYPE SET
--	+ DATA DEFINITION
--	+ COMBINATOR
--		- Singleton
--		- Insert
--		- Merge
--		- Map
-- * NUMBERED
-- * BOOL

---------------------------------------------------------------------------
-- TYPE SET
---------------------------------------------------------------------------

-- DATA DEFINITION

infixr 5 :~
data Set a = Nil | a :~ Set a

-- COMBINATOR

-- Singleton

type Singleton t = t ':~ 'Nil

-- Insert

infixr 5 :-
type t :- ts = t `Insert` ts

type family Insert (t :: Type) (ts :: Set Type) :: Set Type where
	Insert t 'Nil = t ':~ 'Nil
	Insert t (t ':~ ts) = t ':~ ts
	Insert t (t' ':~ ts) = BOOL
		(InsertElse t t' ts)
		(InsertThen t t' ts)
			$ (Number t <=? Number t')

data InsertElse t t' ts :: () >-> k
type instance InsertElse  t t' ts $ '() = t' ':~ t :- ts

data InsertThen t t' ts :: () >-> k
type instance InsertThen t t' ts $ '() = t ':~ t' ':~ ts

-- Merge

infixr 5 :+:
type ts :+: ts' = ts `Merge` ts'

type family Merge (ts :: Set Type) (ts' :: Set Type) :: Set Type where
	Merge ts 'Nil = ts
	Merge 'Nil ts' = ts'
	Merge (t ':~ ts) (t ':~ ts') = t ':~ Merge ts ts'
	Merge (t ':~ ts) (t' ':~ ts') = BOOL
		(MergeElse t ts t' ts')
		(MergeThen t ts t' ts')
			$ (Number t <=? Number t')

data MergeElse t ts t' ts' :: () >-> k
type instance MergeElse t ts t' ts' $ '() = t' ':~ (t ':~ ts) :+: ts'

data MergeThen t ts t' ts' :: () >-> k
type instance MergeThen t ts t' ts' $ '() = t ':~ ts :+: (t' ':~ ts')

-- Map

type family Map (f :: Type -> Type) (ts :: Set Type) :: Set Type where
	_ `Map` 'Nil = 'Nil
	f `Map` (t ':~ ts) = f t ':~ (f `Map` ts)

---------------------------------------------------------------------------
-- NUMBERED
---------------------------------------------------------------------------

class Numbered a where type Number (a :: Type) = (r :: Nat) | r -> a

numbered :: TypeQ -> DecsQ
numbered t = ((: []) <$>)
	. instanceD (cxt []) (conT ''Numbered `appT` t) . (: [])
		$ tySynInstD . tySynEqn Nothing (conT ''Number `appT` t)
			. litT . numTyLit =<< runIO (randomRIO (0, 2 ^ s - 1))
	where s = 64 :: Int

---------------------------------------------------------------------------
-- BOOL
---------------------------------------------------------------------------

type a >-> b = (b -> Type) -> a -> Type
type family ($) (f :: a >-> b) (x :: a) :: b

data BOOL :: (() >-> k) -> (() >-> k) -> (Bool >-> k)
type instance (BOOL f _) $ 'False = f $ '()
type instance (BOOL _ t) $ 'True = t $ '()