module Unison.Hashing.V2.Type
  ( Type,
    TypeF (..),
    bindExternal,
    bindReferences,

    -- * find by type index stuff
    typeToReference,
    typeToReferenceMentions,

    -- * builtin term references
    booleanRef,
    charRef,
    effectRef,
    floatRef,
    intRef,
    listRef,
    natRef,
    textRef,
  )
where

import Data.Map qualified as Map
import Data.Set qualified as Set
import Unison.ABT qualified as ABT
import Unison.HashQualified qualified as HQ
import Unison.Hashing.V2.ABT qualified as ABT
import Unison.Hashing.V2.Kind qualified as K
import Unison.Hashing.V2.Reference (Reference (..), pattern ReferenceDerived)
import Unison.Hashing.V2.Tokenizable (Hashable1)
import Unison.Hashing.V2.Tokenizable qualified as Hashable
import Unison.Name qualified as Name
import Unison.Names.ResolutionResult qualified as Names
import Unison.Prelude
import Unison.Util.List qualified as List
import Unison.Var (Var)

-- | Base functor for types in the Unison language
data TypeF a
  = TypeRef Reference
  | TypeArrow a a
  | TypeAnn a K.Kind
  | TypeApp a a
  | TypeEffect a a
  | TypeEffects [a]
  | TypeForall a
  | TypeIntroOuter a -- binder like ∀, used to introduce variables that are
  -- bound by outer type signatures, to support scoped type
  -- variables
  deriving ((forall m. Monoid m => TypeF m -> m)
-> (forall m a. Monoid m => (a -> m) -> TypeF a -> m)
-> (forall m a. Monoid m => (a -> m) -> TypeF a -> m)
-> (forall a b. (a -> b -> b) -> b -> TypeF a -> b)
-> (forall a b. (a -> b -> b) -> b -> TypeF a -> b)
-> (forall b a. (b -> a -> b) -> b -> TypeF a -> b)
-> (forall b a. (b -> a -> b) -> b -> TypeF a -> b)
-> (forall a. (a -> a -> a) -> TypeF a -> a)
-> (forall a. (a -> a -> a) -> TypeF a -> a)
-> (forall a. TypeF a -> [a])
-> (forall a. TypeF a -> Bool)
-> (forall a. TypeF a -> Int)
-> (forall a. Eq a => a -> TypeF a -> Bool)
-> (forall a. Ord a => TypeF a -> a)
-> (forall a. Ord a => TypeF a -> a)
-> (forall a. Num a => TypeF a -> a)
-> (forall a. Num a => TypeF a -> a)
-> Foldable TypeF
forall a. Eq a => a -> TypeF a -> Bool
forall a. Num a => TypeF a -> a
forall a. Ord a => TypeF a -> a
forall m. Monoid m => TypeF m -> m
forall a. TypeF a -> Bool
forall a. TypeF a -> Int
forall a. TypeF a -> [a]
forall a. (a -> a -> a) -> TypeF a -> a
forall m a. Monoid m => (a -> m) -> TypeF a -> m
forall b a. (b -> a -> b) -> b -> TypeF a -> b
forall a b. (a -> b -> b) -> b -> TypeF a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
$cfold :: forall m. Monoid m => TypeF m -> m
fold :: forall m. Monoid m => TypeF m -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> TypeF a -> m
foldMap :: forall m a. Monoid m => (a -> m) -> TypeF a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> TypeF a -> m
foldMap' :: forall m a. Monoid m => (a -> m) -> TypeF a -> m
$cfoldr :: forall a b. (a -> b -> b) -> b -> TypeF a -> b
foldr :: forall a b. (a -> b -> b) -> b -> TypeF a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> TypeF a -> b
foldr' :: forall a b. (a -> b -> b) -> b -> TypeF a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> TypeF a -> b
foldl :: forall b a. (b -> a -> b) -> b -> TypeF a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> TypeF a -> b
foldl' :: forall b a. (b -> a -> b) -> b -> TypeF a -> b
$cfoldr1 :: forall a. (a -> a -> a) -> TypeF a -> a
foldr1 :: forall a. (a -> a -> a) -> TypeF a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> TypeF a -> a
foldl1 :: forall a. (a -> a -> a) -> TypeF a -> a
$ctoList :: forall a. TypeF a -> [a]
toList :: forall a. TypeF a -> [a]
$cnull :: forall a. TypeF a -> Bool
null :: forall a. TypeF a -> Bool
$clength :: forall a. TypeF a -> Int
length :: forall a. TypeF a -> Int
$celem :: forall a. Eq a => a -> TypeF a -> Bool
elem :: forall a. Eq a => a -> TypeF a -> Bool
$cmaximum :: forall a. Ord a => TypeF a -> a
maximum :: forall a. Ord a => TypeF a -> a
$cminimum :: forall a. Ord a => TypeF a -> a
minimum :: forall a. Ord a => TypeF a -> a
$csum :: forall a. Num a => TypeF a -> a
sum :: forall a. Num a => TypeF a -> a
$cproduct :: forall a. Num a => TypeF a -> a
product :: forall a. Num a => TypeF a -> a
Foldable, (forall a b. (a -> b) -> TypeF a -> TypeF b)
-> (forall a b. a -> TypeF b -> TypeF a) -> Functor TypeF
forall a b. a -> TypeF b -> TypeF a
forall a b. (a -> b) -> TypeF a -> TypeF b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> TypeF a -> TypeF b
fmap :: forall a b. (a -> b) -> TypeF a -> TypeF b
$c<$ :: forall a b. a -> TypeF b -> TypeF a
<$ :: forall a b. a -> TypeF b -> TypeF a
Functor, Functor TypeF
Foldable TypeF
(Functor TypeF, Foldable TypeF) =>
(forall (f :: * -> *) a b.
 Applicative f =>
 (a -> f b) -> TypeF a -> f (TypeF b))
-> (forall (f :: * -> *) a.
    Applicative f =>
    TypeF (f a) -> f (TypeF a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> TypeF a -> m (TypeF b))
-> (forall (m :: * -> *) a. Monad m => TypeF (m a) -> m (TypeF a))
-> Traversable TypeF
forall (t :: * -> *).
(Functor t, Foldable t) =>
(forall (f :: * -> *) a b.
 Applicative f =>
 (a -> f b) -> t a -> f (t b))
-> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> t a -> m (t b))
-> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
-> Traversable t
forall (m :: * -> *) a. Monad m => TypeF (m a) -> m (TypeF a)
forall (f :: * -> *) a. Applicative f => TypeF (f a) -> f (TypeF a)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> TypeF a -> m (TypeF b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> TypeF a -> f (TypeF b)
$ctraverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> TypeF a -> f (TypeF b)
traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> TypeF a -> f (TypeF b)
$csequenceA :: forall (f :: * -> *) a. Applicative f => TypeF (f a) -> f (TypeF a)
sequenceA :: forall (f :: * -> *) a. Applicative f => TypeF (f a) -> f (TypeF a)
$cmapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> TypeF a -> m (TypeF b)
mapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> TypeF a -> m (TypeF b)
$csequence :: forall (m :: * -> *) a. Monad m => TypeF (m a) -> m (TypeF a)
sequence :: forall (m :: * -> *) a. Monad m => TypeF (m a) -> m (TypeF a)
Traversable)

-- | Types are represented as ABTs over the base functor F, with variables in `v`
type Type v a = ABT.Term TypeF v a

freeVars :: Type v a -> Set v
freeVars :: forall v a. Type v a -> Set v
freeVars = Term TypeF v a -> Set v
forall (f :: * -> *) v a. Term f v a -> Set v
ABT.freeVars

bindExternal ::
  (ABT.Var v) => [(v, Reference)] -> Type v a -> Type v a
bindExternal :: forall v a. Var v => [(v, Reference)] -> Type v a -> Type v a
bindExternal [(v, Reference)]
bs = [(v, Term TypeF v ())] -> Term TypeF v a -> Term TypeF v a
forall (f :: * -> *) v b a.
(Foldable f, Functor f, Var v) =>
[(v, Term f v b)] -> Term f v a -> Term f v a
ABT.substsInheritAnnotation [(v
v, () -> Reference -> Term TypeF v ()
forall v a. Ord v => a -> Reference -> Type v a
ref () Reference
r) | (v
v, Reference
r) <- [(v, Reference)]
bs]

bindReferences ::
  (Var v) =>
  (v -> Name.Name) ->
  Set v ->
  Map Name.Name Reference ->
  Type v a ->
  Names.ResolutionResult a (Type v a)
bindReferences :: forall v a.
Var v =>
(v -> Name)
-> Set v
-> Map Name Reference
-> Type v a
-> ResolutionResult a (Type v a)
bindReferences v -> Name
unsafeVarToName Set v
keepFree Map Name Reference
ns Type v a
t =
  let fvs :: [(v, a)]
fvs = Set v -> Type v a -> [(v, a)]
forall (f :: * -> *) v a.
(Traversable f, Ord v) =>
Set v -> Term f v a -> [(v, a)]
ABT.freeVarOccurrences Set v
keepFree Type v a
t
      rs :: [(v, a, Maybe Reference)]
rs = [(v
v, a
a, Name -> Map Name Reference -> Maybe Reference
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (v -> Name
unsafeVarToName v
v) Map Name Reference
ns) | (v
v, a
a) <- [(v, a)]
fvs]
      ok :: (v, annotation, Maybe b)
-> Either (f (ResolutionFailure annotation)) (v, b)
ok (v
v, annotation
_a, Just b
r) = (v, b) -> Either (f (ResolutionFailure annotation)) (v, b)
forall a. a -> Either (f (ResolutionFailure annotation)) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (v
v, b
r)
      ok (v
v, annotation
a, Maybe b
Nothing) = f (ResolutionFailure annotation)
-> Either (f (ResolutionFailure annotation)) (v, b)
forall a b. a -> Either a b
Left (ResolutionFailure annotation -> f (ResolutionFailure annotation)
forall a. a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (HashQualified Name
-> annotation
-> ResolutionError TypeReference
-> ResolutionFailure annotation
forall annotation.
HashQualified Name
-> annotation
-> ResolutionError TypeReference
-> ResolutionFailure annotation
Names.TypeResolutionFailure (Name -> HashQualified Name
forall n. n -> HashQualified n
HQ.NameOnly (v -> Name
unsafeVarToName v
v)) annotation
a ResolutionError TypeReference
forall ref. ResolutionError ref
Names.NotFound))
   in ((v, a, Maybe Reference)
 -> Either (Seq (ResolutionFailure a)) (v, Reference))
-> [(v, a, Maybe Reference)]
-> Either (Seq (ResolutionFailure a)) [(v, Reference)]
forall e (f :: * -> *) a b.
(Semigroup e, Foldable f) =>
(a -> Either e b) -> f a -> Either e [b]
List.validate (v, a, Maybe Reference)
-> Either (Seq (ResolutionFailure a)) (v, Reference)
forall {f :: * -> *} {annotation} {b}.
Applicative f =>
(v, annotation, Maybe b)
-> Either (f (ResolutionFailure annotation)) (v, b)
ok [(v, a, Maybe Reference)]
rs Either (Seq (ResolutionFailure a)) [(v, Reference)]
-> ([(v, Reference)] -> Type v a)
-> Either (Seq (ResolutionFailure a)) (Type v a)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \[(v, Reference)]
es -> [(v, Reference)] -> Type v a -> Type v a
forall v a. Var v => [(v, Reference)] -> Type v a -> Type v a
bindExternal [(v, Reference)]
es Type v a
t

-- some smart patterns
pattern TypeRef' :: Reference -> ABT.Term TypeF v a
pattern $mTypeRef' :: forall {r} {v} {a}.
Term TypeF v a -> (Reference -> r) -> ((# #) -> r) -> r
TypeRef' r <- ABT.Tm' (TypeRef r)

pattern ForallsNamed' :: [v] -> Type v a -> Type v a
pattern $mForallsNamed' :: forall {r} {v} {a}.
Type v a -> ([v] -> Type v a -> r) -> ((# #) -> r) -> r
ForallsNamed' vs body <- (unForalls -> Just (vs, body))

pattern ForallNamed' :: v -> ABT.Term TypeF v a -> ABT.Term TypeF v a
pattern $mForallNamed' :: forall {r} {v} {a}.
Term TypeF v a -> (v -> Term TypeF v a -> r) -> ((# #) -> r) -> r
ForallNamed' v body <- ABT.Tm' (TypeForall (ABT.out -> ABT.Abs v body))

unForalls :: Type v a -> Maybe ([v], Type v a)
unForalls :: forall v a. Type v a -> Maybe ([v], Type v a)
unForalls Type v a
t = Type v a -> [v] -> Maybe ([v], Type v a)
forall {a} {a}.
Term TypeF a a -> [a] -> Maybe ([a], Term TypeF a a)
go Type v a
t []
  where
    go :: Term TypeF a a -> [a] -> Maybe ([a], Term TypeF a a)
go (ForallNamed' a
v Term TypeF a a
body) [a]
vs = Term TypeF a a -> [a] -> Maybe ([a], Term TypeF a a)
go Term TypeF a a
body (a
v a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
vs)
    go Term TypeF a a
_body [] = Maybe ([a], Term TypeF a a)
forall a. Maybe a
Nothing
    go Term TypeF a a
body [a]
vs = ([a], Term TypeF a a) -> Maybe ([a], Term TypeF a a)
forall a. a -> Maybe a
Just ([a] -> [a]
forall a. [a] -> [a]
reverse [a]
vs, Term TypeF a a
body)

-- some smart constructors
ref :: (Ord v) => a -> Reference -> Type v a
ref :: forall v a. Ord v => a -> Reference -> Type v a
ref a
a = a -> TypeF (Term TypeF v a) -> Term TypeF v a
forall (f :: * -> *) v a.
(Foldable f, Ord v) =>
a -> f (Term f v a) -> Term f v a
ABT.tm' a
a (TypeF (Term TypeF v a) -> Term TypeF v a)
-> (Reference -> TypeF (Term TypeF v a))
-> Reference
-> Term TypeF v a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Reference -> TypeF (Term TypeF v a)
forall a. Reference -> TypeF a
TypeRef

intRef, natRef, floatRef, booleanRef, textRef, charRef, listRef, effectRef :: Reference
intRef :: Reference
intRef = Text -> Reference
ReferenceBuiltin Text
"Int"
natRef :: Reference
natRef = Text -> Reference
ReferenceBuiltin Text
"Nat"
floatRef :: Reference
floatRef = Text -> Reference
ReferenceBuiltin Text
"Float"
booleanRef :: Reference
booleanRef = Text -> Reference
ReferenceBuiltin Text
"Boolean"
textRef :: Reference
textRef = Text -> Reference
ReferenceBuiltin Text
"Text"
charRef :: Reference
charRef = Text -> Reference
ReferenceBuiltin Text
"Char"
listRef :: Reference
listRef = Text -> Reference
ReferenceBuiltin Text
"Sequence"
effectRef :: Reference
effectRef = Text -> Reference
ReferenceBuiltin Text
"Effect"

forAll :: (Ord v) => a -> v -> Type v a -> Type v a
forAll :: forall v a. Ord v => a -> v -> Type v a -> Type v a
forAll a
a v
v Type v a
body = a -> TypeF (Type v a) -> Type v a
forall (f :: * -> *) v a.
(Foldable f, Ord v) =>
a -> f (Term f v a) -> Term f v a
ABT.tm' a
a (Type v a -> TypeF (Type v a)
forall a. a -> TypeF a
TypeForall (a -> v -> Type v a -> Type v a
forall v a (f :: * -> *).
Ord v =>
a -> v -> Term f v a -> Term f v a
ABT.abs' a
a v
v Type v a
body))

-- | Bind the given variables with an outer `forall`, if they are used in `t`.
generalize :: (Ord v) => [v] -> Type v a -> Type v a
generalize :: forall v a. Ord v => [v] -> Type v a -> Type v a
generalize [v]
vs Type v a
t = (v -> Type v a -> Type v a) -> Type v a -> [v] -> Type v a
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr v -> Type v a -> Type v a
forall {v} {a}. Ord v => v -> Term TypeF v a -> Term TypeF v a
f Type v a
t [v]
vs
  where
    f :: v -> Term TypeF v a -> Term TypeF v a
f v
v Term TypeF v a
t =
      if v -> Set v -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member v
v (Term TypeF v a -> Set v
forall (f :: * -> *) v a. Term f v a -> Set v
ABT.freeVars Term TypeF v a
t) then a -> v -> Term TypeF v a -> Term TypeF v a
forall v a. Ord v => a -> v -> Type v a -> Type v a
forAll (Term TypeF v a -> a
forall (f :: * -> *) v a. Term f v a -> a
ABT.annotation Term TypeF v a
t) v
v Term TypeF v a
t else Term TypeF v a
t

unforall' :: Type v a -> ([v], Type v a)
unforall' :: forall v a. Type v a -> ([v], Type v a)
unforall' (ForallsNamed' [v]
vs Type v a
t) = ([v]
vs, Type v a
t)
unforall' Type v a
t = ([], Type v a
t)

typeToReference :: (Ord v, Show v) => Type v a -> Reference
typeToReference :: forall v a. (Ord v, Show v) => Type v a -> Reference
typeToReference (TypeRef' Reference
r) = Reference
r
-- a bit of normalization - any unused type parameters aren't part of the hash
typeToReference (ForallNamed' v
v Term TypeF v a
body) | Bool -> Bool
not (v -> Set v -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member v
v (Term TypeF v a -> Set v
forall (f :: * -> *) v a. Term f v a -> Set v
ABT.freeVars Term TypeF v a
body)) = Term TypeF v a -> Reference
forall v a. (Ord v, Show v) => Type v a -> Reference
typeToReference Term TypeF v a
body
typeToReference Term TypeF v a
t = Hash -> Pos -> Reference
ReferenceDerived (Term TypeF v a -> Hash
forall (f :: * -> *) v a.
(Functor f, Hashable1 f, Eq v, Show v) =>
Term f v a -> Hash
ABT.hash Term TypeF v a
t) Pos
0

typeToReferenceMentions :: (Ord v, Show v) => Type v a -> Set Reference
typeToReferenceMentions :: forall v a. (Ord v, Show v) => Type v a -> Set Reference
typeToReferenceMentions Type v a
ty =
  let ([v]
vs, Type v a
_) = Type v a -> ([v], Type v a)
forall v a. Type v a -> ([v], Type v a)
unforall' Type v a
ty
      gen :: Type v a -> Type v a
gen Type v a
ty = [v] -> Type v a -> Type v a
forall v a. Ord v => [v] -> Type v a -> Type v a
generalize (Set v -> [v]
forall a. Set a -> [a]
Set.toList (Type v a -> Set v
forall v a. Type v a -> Set v
freeVars Type v a
ty)) (Type v a -> Type v a) -> Type v a -> Type v a
forall a b. (a -> b) -> a -> b
$ [v] -> Type v a -> Type v a
forall v a. Ord v => [v] -> Type v a -> Type v a
generalize [v]
vs Type v a
ty
   in [Reference] -> Set Reference
forall a. Ord a => [a] -> Set a
Set.fromList ([Reference] -> Set Reference) -> [Reference] -> Set Reference
forall a b. (a -> b) -> a -> b
$ Type v a -> Reference
forall v a. (Ord v, Show v) => Type v a -> Reference
typeToReference (Type v a -> Reference)
-> (Type v a -> Type v a) -> Type v a -> Reference
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type v a -> Type v a
forall {a}. Type v a -> Type v a
gen (Type v a -> Reference) -> [Type v a] -> [Reference]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Type v a -> [Type v a]
forall v (f :: * -> *) a.
(Ord v, Traversable f) =>
Term f v a -> [Term f v a]
ABT.subterms Type v a
ty

instance Hashable1 TypeF where
  hash1 :: forall a.
([a] -> ([Hash], a -> Hash)) -> (a -> Hash) -> TypeF a -> Hash
hash1 [a] -> ([Hash], a -> Hash)
hashCycle a -> Hash
hash TypeF a
e =
    let (Word8 -> Token
tag, Hash -> Token
hashed) = (Word8 -> Token
Hashable.Tag, Hash -> Token
Hashable.Hashed)
     in -- Note: start each layer with leading `0` byte, to avoid collisions with
        -- terms, which start each layer with leading `1`. See `Hashable1 Term.F`
        [Token] -> Hash
Hashable.accumulate ([Token] -> Hash) -> [Token] -> Hash
forall a b. (a -> b) -> a -> b
$
          Word8 -> Token
tag Word8
0 Token -> [Token] -> [Token]
forall a. a -> [a] -> [a]
: case TypeF a
e of
            TypeRef Reference
r -> [Word8 -> Token
tag Word8
0, Reference -> Token
forall t. Tokenizable t => t -> Token
Hashable.accumulateToken Reference
r]
            TypeArrow a
a a
b -> [Word8 -> Token
tag Word8
1, Hash -> Token
hashed (a -> Hash
hash a
a), Hash -> Token
hashed (a -> Hash
hash a
b)]
            TypeApp a
a a
b -> [Word8 -> Token
tag Word8
2, Hash -> Token
hashed (a -> Hash
hash a
a), Hash -> Token
hashed (a -> Hash
hash a
b)]
            TypeAnn a
a Kind
k -> [Word8 -> Token
tag Word8
3, Hash -> Token
hashed (a -> Hash
hash a
a), Kind -> Token
forall t. Tokenizable t => t -> Token
Hashable.accumulateToken Kind
k]
            -- Example:
            --   a) {Remote, Abort} (() -> {Remote} ()) should hash the same as
            --   b) {Abort, Remote} (() -> {Remote} ()) but should hash differently from
            --   c) {Remote, Abort} (() -> {Abort} ())
            TypeEffects [a]
es ->
              let ([Hash]
hs, a -> Hash
_) = [a] -> ([Hash], a -> Hash)
hashCycle [a]
es
               in Word8 -> Token
tag Word8
4 Token -> [Token] -> [Token]
forall a. a -> [a] -> [a]
: (Hash -> Token) -> [Hash] -> [Token]
forall a b. (a -> b) -> [a] -> [b]
map Hash -> Token
hashed [Hash]
hs
            TypeEffect a
e a
t -> [Word8 -> Token
tag Word8
5, Hash -> Token
hashed (a -> Hash
hash a
e), Hash -> Token
hashed (a -> Hash
hash a
t)]
            TypeForall a
a -> [Word8 -> Token
tag Word8
6, Hash -> Token
hashed (a -> Hash
hash a
a)]
            TypeIntroOuter a
a -> [Word8 -> Token
tag Word8
7, Hash -> Token
hashed (a -> Hash
hash a
a)]