{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Patat.Unique
    ( Unique
    , UniqueGen
    , zeroUniqueGen
    , freshUnique
    ) where

import           Data.Hashable (Hashable)

-- | Can be used as a unique identifier.
newtype Unique = Unique Int deriving (Eq Unique
Eq Unique =>
(Int -> Unique -> Int) -> (Unique -> Int) -> Hashable Unique
Int -> Unique -> Int
Unique -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> Unique -> Int
hashWithSalt :: Int -> Unique -> Int
$chash :: Unique -> Int
hash :: Unique -> Int
Hashable, Unique -> Unique -> Bool
(Unique -> Unique -> Bool)
-> (Unique -> Unique -> Bool) -> Eq Unique
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Unique -> Unique -> Bool
== :: Unique -> Unique -> Bool
$c/= :: Unique -> Unique -> Bool
/= :: Unique -> Unique -> Bool
Eq, Eq Unique
Eq Unique =>
(Unique -> Unique -> Ordering)
-> (Unique -> Unique -> Bool)
-> (Unique -> Unique -> Bool)
-> (Unique -> Unique -> Bool)
-> (Unique -> Unique -> Bool)
-> (Unique -> Unique -> Unique)
-> (Unique -> Unique -> Unique)
-> Ord Unique
Unique -> Unique -> Bool
Unique -> Unique -> Ordering
Unique -> Unique -> Unique
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Unique -> Unique -> Ordering
compare :: Unique -> Unique -> Ordering
$c< :: Unique -> Unique -> Bool
< :: Unique -> Unique -> Bool
$c<= :: Unique -> Unique -> Bool
<= :: Unique -> Unique -> Bool
$c> :: Unique -> Unique -> Bool
> :: Unique -> Unique -> Bool
$c>= :: Unique -> Unique -> Bool
>= :: Unique -> Unique -> Bool
$cmax :: Unique -> Unique -> Unique
max :: Unique -> Unique -> Unique
$cmin :: Unique -> Unique -> Unique
min :: Unique -> Unique -> Unique
Ord, Int -> Unique -> ShowS
[Unique] -> ShowS
Unique -> String
(Int -> Unique -> ShowS)
-> (Unique -> String) -> ([Unique] -> ShowS) -> Show Unique
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Unique -> ShowS
showsPrec :: Int -> Unique -> ShowS
$cshow :: Unique -> String
show :: Unique -> String
$cshowList :: [Unique] -> ShowS
showList :: [Unique] -> ShowS
Show)

-- | Used to generate fresh variables.
newtype UniqueGen = UniqueGen Int deriving (Int -> UniqueGen -> ShowS
[UniqueGen] -> ShowS
UniqueGen -> String
(Int -> UniqueGen -> ShowS)
-> (UniqueGen -> String)
-> ([UniqueGen] -> ShowS)
-> Show UniqueGen
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> UniqueGen -> ShowS
showsPrec :: Int -> UniqueGen -> ShowS
$cshow :: UniqueGen -> String
show :: UniqueGen -> String
$cshowList :: [UniqueGen] -> ShowS
showList :: [UniqueGen] -> ShowS
Show)

zeroUniqueGen :: UniqueGen
zeroUniqueGen :: UniqueGen
zeroUniqueGen = Int -> UniqueGen
UniqueGen Int
0

freshUnique :: UniqueGen -> (Unique, UniqueGen)
freshUnique :: UniqueGen -> (Unique, UniqueGen)
freshUnique (UniqueGen Int
x) = (Int -> Unique
Unique Int
x, Int -> UniqueGen
UniqueGen (Int
x Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1))