packages feed

hell 666.20250113 → 666.20251111

raw patch · 2 files changed

+3202/−2397 lines, 2 filesdep +criteriondep +criterion-measurementdep +thesedep ~base

Dependencies added: criterion, criterion-measurement, these, time

Dependency ranges changed: base

Files

hell.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.36.0.+-- This file has been generated from package.yaml by hpack version 0.37.0. -- -- see: https://github.com/sol/hpack  name:           hell-version:        666.20250113+version:        666.20251111 synopsis:       Haskell-based shell scripting language author:         Chris Done maintainer:     Chris Done@@ -22,10 +22,12 @@       QuickCheck     , aeson     , async-    , base >=4.17.2.1 && <4.18+    , base >=4.17.2.1 && <4.22     , bytestring     , constraints     , containers+    , criterion+    , criterion-measurement     , directory     , ghc-prim     , haskell-src-exts@@ -39,6 +41,44 @@     , text     , th-lift     , th-orphans+    , these+    , time+    , typed-process+    , unliftio+    , vector+  default-language: Haskell2010++test-suite hell-test+  type: exitcode-stdio-1.0+  main-is: src/Hell.hs+  other-modules:+      Paths_hell+  ghc-options: -Wall -Wno-missing-pattern-synonym-signatures -O2 -main-is Main.specMain -threaded -rtsopts+  build-depends:+      QuickCheck+    , aeson+    , async+    , base >=4.17.2.1 && <4.22+    , bytestring+    , constraints+    , containers+    , criterion+    , criterion-measurement+    , directory+    , ghc-prim+    , haskell-src-exts+    , hspec+    , lucid2+    , mtl+    , optparse-applicative+    , syb+    , template-haskell+    , temporary+    , text+    , th-lift+    , th-orphans+    , these+    , time     , typed-process     , unliftio     , vector
src/Hell.hs view
@@ -1,2395 +1,3160 @@ {-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE BlockArguments #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DeriveFoldable #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE ExtendedDefaultRules #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedRecordDot #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE PatternSynonyms #-}-{-# LANGUAGE PolyKinds #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE ViewPatterns #-}------ Welcome to Hell------ Haskell as a scripting language!------ Special thanks to Stephanie Weirich, whose type-safe typechecker--- this is built upon, and for the Type.Reflection module, which has--- made some of this more ergonomic.-{-# OPTIONS_GHC -Wno-unused-foralls #-}--module Main (main) where---- All modules tend to be imported qualified by their last component,--- e.g. 'Data.Graph' becomes 'Graph', and are then exposed to the Hell--- guest language as such.--#if __GLASGOW_HASKELL__ >= 906-import Control.Monad-#endif-import qualified Control.Concurrent as Concurrent-import Control.Monad.Reader-import Control.Monad.State.Strict-import Data.Aeson (Value)-import qualified Data.Aeson as Json-import qualified Data.Aeson.KeyMap as KeyMap-import Data.Bifunctor-import qualified Data.Bool as Bool-import Data.ByteString (ByteString)-import qualified Data.ByteString as ByteString-import qualified Data.ByteString.Builder as ByteString hiding (writeFile)-import qualified Data.ByteString.Lazy as L-import Data.Containers.ListUtils-import qualified Data.Either as Either-import qualified Data.Eq as Eq-import Data.Foldable-import qualified Data.Function as Function-import qualified Data.Generics as SYB-import qualified Data.Graph as Graph-import qualified Data.List as List-import qualified Data.Map as Map-import Data.Map.Strict (Map)-import qualified Data.Maybe as Maybe-import qualified Data.Ord as Ord-import Data.Set (Set)-import qualified Data.Set as Set-import Data.Text (Text)-import qualified Data.Text as Text-import Data.Tree (Tree)-import qualified Data.Tree as Tree-import qualified Data.Text.Encoding as Text-import qualified Data.Text.IO as Text-import Data.Traversable-import Data.Vector (Vector)-import qualified Data.Vector as Vector-import Data.Void-import GHC.TypeLits-import GHC.Types (Type)-import qualified Language.Haskell.Exts as HSE-import Language.Haskell.TH (Q)-import qualified Language.Haskell.TH as TH-import Language.Haskell.TH.Instances ()-import qualified Language.Haskell.TH.Syntax as TH-import Lucid hiding (Term, for_, term)-import qualified Options.Applicative as Options-import Options.Applicative (Parser)-import qualified System.Directory as Dir-import System.Environment-import qualified System.Exit as Exit-import qualified System.IO as IO-import qualified System.IO.Temp as Temp-import System.Process.Typed as Process-import qualified System.Timeout as Timeout-import Test.Hspec-import qualified Text.Read as Read-import qualified Text.Show as Show-import Type.Reflection (SomeTypeRep (..), TypeRep, typeRep, typeRepKind, pattern TypeRep)-import qualified Type.Reflection as Type-import qualified UnliftIO.Async as Async----------------------------------------------------------------------------------- Main entry point---- | Commands available.-data Command-  = Run FilePath-  | Check FilePath-  | Version---- | Main entry point.-main :: IO ()-main = do-  args <- getArgs-  case args of-    (x : ys)-      | not (List.isPrefixOf "-" x) -> withArgs ys $ dispatch (Run x)-    _ -> dispatch =<< Options.execParser opts-  where-    opts =-      Options.info-        (commandParser Options.<**> Options.helper)-        ( Options.fullDesc-            <> Options.progDesc "Runs and typechecks Hell scripts"-            <> Options.header "hell - A Haskell-driven scripting language"-        )---- | Command options.-commandParser :: Options.Parser Command-commandParser =-  Options.asum-    [ Run <$> Options.strArgument (Options.metavar "FILE" <> Options.help "Run the given .hell file"),-      Check <$> Options.strOption (Options.long "check" <> Options.metavar "FILE" <> Options.help "Typecheck the given .hell file"),-      Version <$ Options.flag () () (Options.long "version" <> Options.help "Print the version")-    ]---- | Version of Hell.-hellVersion :: Text-hellVersion = "2025-01-13"---- | Dispatch on the command.-dispatch :: Command -> IO ()-dispatch Version = Text.putStrLn hellVersion-dispatch (Run filePath) = do-  action <- compileFile filePath-  eval () action-dispatch (Check filePath) = do-  void $ compileFile filePath------------------------------------------------------------------------------------- Compiler---- | Parses the file with HSE, desugars it, infers it, checks it,--- returns it. Or throws an error.-compileFile :: FilePath -> IO (Term () (IO ()))-compileFile filePath = do-  result <- parseFile filePath-  case result of-    Left e -> error $ e-    Right File{terms,types}-      | anyCycles terms -> error "Cyclic bindings are not supported!"-      | anyCycles types -> error "Cyclic types are not supported!"-      | otherwise ->-          case desugarAll types terms of-            Left err -> error $ prettyString err-            Right dterms ->-              case lookup "main" dterms of-                Nothing -> error "No main declaration!"-                Just main' ->-                  case inferExp mempty main' of-                    Left err -> error $ prettyString err-                    Right uterm ->-                      case check uterm Nil of-                        Left err -> error $ prettyString err-                        Right (Typed t ex) ->-                          case Type.eqTypeRep (typeRepKind t) (typeRep @Type) of-                            Nothing -> error $ "Kind error, that's nowhere near an IO ()!"-                            Just Type.HRefl ->-                              case Type.eqTypeRep t (typeRep @(IO ())) of-                                Just Type.HRefl ->-                                  pure ex-                                Nothing -> error $ "Type isn't IO (), but: " ++ show t------------------------------------------------------------------------------------- Get declarations from the module--parseModule :: HSE.Module HSE.SrcSpanInfo -> HSE.ParseResult File-parseModule (HSE.Module _ Nothing [] [] decls) = do-  termsAndTypes <- traverse parseDecl decls-  let terms = concatMap fst termsAndTypes-      types = concatMap snd termsAndTypes-  let names = map fst terms-      tyNames = map fst types-  if Set.size (Set.fromList names) == length names &&-     Set.size (Set.fromList tyNames) == length tyNames-    then pure File{terms,types}-    else fail "Duplicate names!"-  where-    parseDecl (HSE.PatBind _ (HSE.PVar _ (HSE.Ident _ string)) (HSE.UnGuardedRhs _ exp') Nothing) =-      pure ([(string, exp')], types)-        where types = []-    parseDecl (HSE.DataDecl _ HSE.DataType {} Nothing (HSE.DHead _ name) [qualConDecl] []) =-      do (termName,termExpr,typeName,typ) <- parseDataDecl name qualConDecl-         pure ([(termName,termExpr)], [(typeName,typ)])-    parseDecl (HSE.DataDecl _ HSE.DataType {} Nothing (HSE.DHead _ name) qualConDecls []) =-      do (terms, tyname, typ) <- parseSumDecl name qualConDecls-         pure (terms, [(tyname,typ)])-    parseDecl _ = fail "Can't parse that!"-parseModule _ = fail "Module headers aren't supported."---- data Value = Text Text | Number Int--- \ x ->---   hell:Hell.Tagged @"Main.Value"---     @(Variant (ConsL "Number" Int (ConsL "Text" Text NilL)))---     (Variant.left @"Number" x)--- \ x ->---   hell:Hell.Tagged @"Main.Value"---     @(Variant (ConsL "Number" Int (ConsL "Text" Text NilL)))---     (Variant.right (Variant.left @"Text" x))-parseSumDecl :: (l ~ HSE.SrcSpanInfo) => HSE.Name l -> [HSE.QualConDecl l] -> HSE.ParseResult ([(String, HSE.Exp HSE.SrcSpanInfo)],-          -- ^^^^^ constructor and term-             String, HSE.Type HSE.SrcSpanInfo)-          -- ^^^^^ type name and type-parseSumDecl (HSE.Ident _ tyname) conDecls0 = do-  conDecls <- fmap Map.fromList $ traverse parseConDecl conDecls0-  let variantType = desugarVariantType $ Map.toList conDecls-  let taggedVariantType =-        -- Example:              Tagged  "Main.Person"  (Variant ..)-        --                       vvvvvv  vvvvvvvv       vvvvvvvvvvv-        HSE.TyApp l (HSE.TyApp l (hellTaggedTyCon l) (tySym qualifiedName)) variantType-  -- Note: the constructors are sorted by name, to provide a canonical ordering.-  let terms = map (makeCons conDecls variantType) $ Map.toList conDecls-  pure (terms, tyname, taggedVariantType)-  where-    l = HSE.noSrcSpan-    makeCons conDecls variantType (conName, typ)-      | HSE.TyCon _ (HSE.Qual _ (HSE.ModuleName _ "hell:Hell") (HSE.Ident _ "Nullary")) <- typ =-          ( conName,-            appTagged variantType $-              desugarVariantCon True (Map.keys conDecls) conName-          )-      | otherwise = (conName, expr)-      where-        expr =-          HSE.Lambda l [HSE.PVar l (HSE.Ident l "x")] $-            appTagged variantType $-              desugarVariantCon False (Map.keys conDecls) conName-    qualifiedName = "Main." ++ tyname-    appTagged ty =-      HSE.App l $-        HSE.App-          l-          ( HSE.App-              l-              (hellTaggedCon l)-              (HSE.TypeApp l (tySym qualifiedName))-          )-          (HSE.TypeApp l ty)-    tySym s = HSE.TyPromoted l (HSE.PromotedString l s s)-parseSumDecl _ _ =-  fail "Sum type declaration not in supported format."--desugarVariantCon :: Bool -> [String] -> String -> HSE.Exp HSE.SrcSpanInfo-desugarVariantCon nullary cons thisCon = rights $ left-  where-    right _ = HSE.Var l (hellQName l "RightV")-    rights e = foldr (HSE.App l) e $ map right $ takeWhile (/= thisCon) cons-    left =-      if nullary-        then-          HSE.App-            l-            left0-            (HSE.Con l (hellQName l "Nullary"))-        else-          HSE.App-            l-            left0-            (HSE.Var l (HSE.UnQual l (HSE.Ident l "x")))-      where-        left0 =-          ( HSE.App-              l-              (HSE.Var l (hellQName l "LeftV"))-              (HSE.TypeApp l (tySym thisCon))-          )-    tySym s = HSE.TyPromoted l (HSE.PromotedString l s s)-    l = HSE.noSrcSpan--desugarVariantType :: [(String, HSE.Type HSE.SrcSpanInfo)] -> HSE.Type HSE.SrcSpanInfo-desugarVariantType = appRecord . foldr appCons nilL-  where-    appCons (name, typ) rest =-      HSE.TyApp l (HSE.TyApp l (HSE.TyApp l consL (tySym name)) typ) rest-    appRecord x =-      HSE.TyParen l (HSE.TyApp l (hellVariantTyCon l) x)-    tySym s = HSE.TyPromoted l (HSE.PromotedString l s s)-    nilL = hellNilTyCon l-    consL = hellConsTyCon l-    l = HSE.noSrcSpan--parseConDecl :: (MonadFail f) => HSE.QualConDecl l -> f (String, HSE.Type l)-parseConDecl (HSE.QualConDecl _ Nothing Nothing (HSE.ConDecl _ (HSE.Ident _ consName) [slot])) =-  pure (consName, slot)-parseConDecl (HSE.QualConDecl l Nothing Nothing (HSE.ConDecl _ (HSE.Ident _ consName) [])) =-  pure ( consName, hellTyCon l "Nullary")-parseConDecl _ = fail "Unsupported constructor declaration format."--parseDataDecl :: (l ~ HSE.SrcSpanInfo) =>-   HSE.Name l ->-   HSE.QualConDecl l ->-   HSE.ParseResult (String,    HSE.Exp HSE.SrcSpanInfo,-   --               ^^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^-   -- Term constructor name... and its expr.--                    String, HSE.Type HSE.SrcSpanInfo)-   --               ^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^^^-   --          Type name... type content.-parseDataDecl (HSE.Ident _ tyname) (HSE.QualConDecl _ Nothing Nothing (HSE.RecDecl _ (HSE.Ident _ consName) fields)) = do-  -- Note: the fields are sorted by name.-  fields' <- fmap (List.sortBy (Ord.comparing fst) . concat) $ traverse getField fields-  let names = map fst fields'-  -- Technically the type checker is quite capable of handling this in-  -- a sound manner, but it's weird and Haskell disallows it, so we-  -- turn it off.-  when (List.nub names /= names) $-    fail "Field names cannot be repeated."-  let ( consExpr , typ ) = makeConstructor tyname fields'-  pure (consName, consExpr, tyname, typ)-  where-    getField (HSE.FieldDecl _ names typ) = do-      names' <- for names \case-        (HSE.Ident _ n) -> pure n-        _ -> fail "Invalid field name."-      pure $ map (,typ) names'-parseDataDecl _ _ =-  fail "Record declaration not in supported format."--makeConstructor :: String -> [(String, HSE.Type HSE.SrcSpanInfo)] ->-  (HSE.Exp HSE.SrcSpanInfo, HSE.Type HSE.SrcSpanInfo)-makeConstructor name fields = (appTagged recordType, taggedRecordType)-  where-    recordType = desugarRecordType fields-    taggedRecordType =-      -- Example:              Tagged  "Main.Person"  (Record ..)-      --                       vvvvvv  vvvvvvvv       vvvvvvvvvvv-      HSE.TyApp l (HSE.TyApp l (hellTaggedTyCon l) (tySym qualifiedName)) recordType-    qualifiedName = "Main." ++ name-    appTagged ty =-      HSE.App-        l-        ( HSE.App-            l-            (hellTaggedCon l)-            (HSE.TypeApp l (tySym qualifiedName))-        )-        (HSE.TypeApp l ty)-    tySym s = HSE.TyPromoted l (HSE.PromotedString l s s)-    l = HSE.noSrcSpan--makeConstructRecord :: HSE.QName HSE.SrcSpanInfo -> [HSE.FieldUpdate HSE.SrcSpanInfo] -> HSE.Exp HSE.SrcSpanInfo-makeConstructRecord qname fields =-  HSE.App l (HSE.Con l qname)-    $ foldr-      ( \(name, expr) rest ->-          let tySym s = HSE.TyPromoted l (HSE.PromotedString l s s)-           in HSE.App-                l-                ( HSE.App-                    l-                    ( HSE.App-                        l-                        (HSE.Var l (hellQName l "ConsR"))-                        (HSE.TypeApp l (tySym name))-                    )-                    expr-                )-                rest-      )-      (HSE.Var l (hellQName l "NilR"))-    $ List.sortBy (Ord.comparing fst)-    $ map-      ( \case-          HSE.FieldUpdate _ (HSE.UnQual _ (HSE.Ident _ i)) expr -> (i, expr)-          f -> error $ "Invalid field: " ++ show f-      )-      fields-  where-    l = HSE.noSrcSpan--desugarRecordType :: [(String, HSE.Type HSE.SrcSpanInfo)] -> HSE.Type HSE.SrcSpanInfo-desugarRecordType = appRecord . foldr appCons nilL-  where-    appCons (name, typ) rest =-      HSE.TyApp l (HSE.TyApp l (HSE.TyApp l consL (tySym name)) typ) rest-    appRecord x =-      HSE.TyApp l (hellRecordTyCon l) x-    tySym s = HSE.TyPromoted l (HSE.PromotedString l s s)-    nilL = hellNilTyCon l-    consL = hellConsTyCon l-    l = HSE.noSrcSpan------------------------------------------------------------------------------------- Typed AST support------ We define a well-typed, well-indexed GADT AST which can be evaluated directly.--data Term g t where-  Var :: Var g t -> Term g t-  Lam :: Term (g, a) b -> Term g (a -> b)-  App :: Term g (s -> t) -> Term g s -> Term g t-  Lit :: a -> Term g a--data Var g t where-  ZVar :: (t -> a) -> Var (h, t) a-  SVar :: Var h t -> Var (h, s) t------------------------------------------------------------------------------------- Evaluator------- This is the entire evaluator. Type-safe and total.-eval :: env -> Term env t -> t-eval env (Var v) = lookp v env-eval env (Lam e) = \x -> eval (env, x) e-eval env (App e1 e2) = (eval env e1) (eval env e2)-eval _env (Lit a) = a---- Type-safe, total lookup. The final @slot@ determines which slot of--- a given tuple to pick out.-lookp :: Var env t -> env -> t-lookp (ZVar slot) (_, x) = slot x-lookp (SVar v) (env, _) = lookp v env------------------------------------------------------------------------------------- The "untyped" AST------ This is the AST that is not interpreted, and is just--- type-checked. The HSE AST is desugared into this one.--data UTerm t-  = UVar HSE.SrcSpanInfo t String-  | ULam HSE.SrcSpanInfo t Binding (Maybe SomeStarType) (UTerm t)-  | UApp HSE.SrcSpanInfo t (UTerm t) (UTerm t)-  | -- IRep below: The variables are poly types, they aren't metavars,-    -- and need to be instantiated.-    UForall HSE.SrcSpanInfo t [SomeTypeRep] Forall [TH.Uniq] (IRep TH.Uniq) [t]-  deriving (Traversable, Functor, Foldable)--typeOf :: UTerm t -> t-typeOf = \case-  UVar _ t _ -> t-  ULam _ t _ _ _ -> t-  UApp _ t _ _ -> t-  UForall _ t _ _ _ _ _ -> t--data Binding = Singleton String | Tuple [String]--data Forall where-  NoClass :: (forall (a :: Type). TypeRep a -> Forall) -> Forall-  SymbolOf :: (forall (a :: Symbol). TypeRep a -> Forall) -> Forall-  StreamTypeOf :: (forall (a :: StreamType). TypeRep a -> Forall) -> Forall-  ListOf :: (forall (a :: List). TypeRep a -> Forall) -> Forall-  OrdEqShow :: (forall (a :: Type). (Ord a, Eq a, Show a) => TypeRep a -> Forall) -> Forall-  Monoidal :: (forall m. (Monoid m) => TypeRep m -> Forall) -> Forall-  Applicable :: (forall (m :: Type -> Type). (Applicative m) => TypeRep m -> Forall) -> Forall-  Monadic :: (forall (m :: Type -> Type). (Monad m) => TypeRep m -> Forall) -> Forall-  GetOf ::-    TypeRep (k :: Symbol) ->-    TypeRep (a :: Type) ->-    TypeRep (t :: Symbol) ->-    TypeRep (r :: List) ->-    ((Tagged t (Record r) -> a) -> Forall) ->-    Forall-  SetOf ::-    TypeRep (k :: Symbol) ->-    TypeRep (a :: Type) ->-    TypeRep (t :: Symbol) ->-    TypeRep (r :: List) ->-    ((a -> Tagged t (Record r) -> Tagged t (Record r)) -> Forall) ->-    Forall-  ModifyOf ::-    TypeRep (k :: Symbol) ->-    TypeRep (a :: Type) ->-    TypeRep (t :: Symbol) ->-    TypeRep (r :: List) ->-    (((a -> a) -> Tagged t (Record r) -> Tagged t (Record r)) -> Forall) ->-    Forall-  Final :: (forall g. Typed (Term g)) -> Forall--lit :: (Type.Typeable a) => a -> UTerm ()-lit = litWithSpan HSE.noSrcSpan--litWithSpan :: (Type.Typeable a) => HSE.SrcSpanInfo -> a -> UTerm ()-litWithSpan srcSpanInfo l = UForall srcSpanInfo () [] (Final (Typed (Type.typeOf l) (Lit l))) [] (fromSomeStarType (SomeStarType (Type.typeOf l))) []--data SomeStarType = forall (a :: Type). SomeStarType (TypeRep a)--deriving instance Show SomeStarType--instance Eq SomeStarType where-  SomeStarType x == SomeStarType y = Type.SomeTypeRep x == Type.SomeTypeRep y--pattern StarTypeRep t <- (toStarType -> Just (SomeStarType t))-  where-    StarTypeRep t = SomeTypeRep t--toStarType :: SomeTypeRep -> Maybe SomeStarType-toStarType (SomeTypeRep t) = do-  Type.HRefl <- Type.eqTypeRep (typeRepKind t) (typeRep @Type)-  pure $ SomeStarType t------------------------------------------------------------------------------------- The type checker--data Typed (thing :: Type -> Type) = forall ty. Typed (TypeRep (ty :: Type)) (thing ty)--data TypeCheckError-  = NotInScope String-  | TupleTypeMismatch-  | TypeCheckMismatch-  | TupleTypeTooBig-  | TypeOfApplicandIsNotFunction-  | LambdaIsNotAFunBug-  | InferredCheckedDisagreeBug-  | LambdaMustBeStarBug-  deriving (Show)--typed :: (Type.Typeable a) => a -> Typed (Term g)-typed l = Typed (Type.typeOf l) (Lit l)---- The type environment and lookup-data TyEnv g where-  Nil :: TyEnv g-  Cons :: Binding -> TypeRep (t :: Type) -> TyEnv h -> TyEnv (h, t)---- The top-level checker used by the main function.-check :: (UTerm SomeTypeRep) -> TyEnv () -> Either TypeCheckError (Typed (Term ()))-check = tc---- Type check a term given an environment of names.-tc :: (UTerm SomeTypeRep) -> TyEnv g -> Either TypeCheckError (Typed (Term g))-tc (UVar _ _ v) env = do-  Typed ty v' <- lookupVar v env-  pure $ Typed ty (Var v')-tc (ULam _ (StarTypeRep lam_ty) s _ body) env =-  case lam_ty of-    Type.Fun bndr_ty' _-      | Just Type.HRefl <- Type.eqTypeRep (typeRepKind bndr_ty') (typeRep @Type) ->-          case tc body (Cons s bndr_ty' env) of-            Left e -> Left e-            Right (Typed body_ty' body') ->-              let checked_ty = Type.Fun bndr_ty' body_ty'-               in case Type.eqTypeRep checked_ty lam_ty of-                    Just Type.HRefl -> Right $ Typed lam_ty (Lam body')-                    Nothing -> Left InferredCheckedDisagreeBug-    _ -> Left LambdaIsNotAFunBug-tc (ULam _ (SomeTypeRep {}) _ _ _) _ =-  Left LambdaMustBeStarBug-tc (UApp _ _ e1 e2) env =-  case tc e1 env of-    Left e -> Left e-    Right (Typed (Type.Fun bndr_ty body_ty) e1') ->-      case tc e2 env of-        Left e -> Left e-        Right (Typed arg_ty e2') ->-          case Type.eqTypeRep arg_ty bndr_ty of-            Nothing ->-              -- error $ "Type error: " ++ show arg_ty ++ " vs " ++ show bndr_ty-              Left TypeCheckMismatch-            Just (Type.HRefl) ->-              let kind = typeRepKind body_ty-               in case Type.eqTypeRep kind (typeRep @Type) of-                    Just Type.HRefl -> Right $ Typed body_ty (App e1' e2')-                    _ -> Left TypeCheckMismatch-    Right {} -> Left TypeOfApplicandIsNotFunction--- Polytyped terms, must be, syntactically, fully-saturated-tc (UForall _ _ _ fall _ _ reps0) _env = go reps0 fall-  where-    go :: [SomeTypeRep] -> Forall -> Either TypeCheckError (Typed (Term g))-    go [] (Final typed') = pure typed'-    go (StarTypeRep rep : reps) (NoClass f) = go reps (f rep)-    go (SomeTypeRep rep : reps) (ListOf f)-      | Just Type.HRefl <- Type.eqTypeRep (typeRepKind rep) (typeRep @List) = go reps (f rep)-    go (SomeTypeRep rep : reps) (SymbolOf f)-      | Just Type.HRefl <- Type.eqTypeRep (typeRepKind rep) (typeRep @Symbol) = go reps (f rep)-    go (SomeTypeRep rep : reps) (StreamTypeOf f)-      | Just Type.HRefl <- Type.eqTypeRep (typeRepKind rep) (typeRep @StreamType) = go reps (f rep)-    go (StarTypeRep rep : reps) (OrdEqShow f) =-      if-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @Int) -> go reps (f rep)-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @Double) -> go reps (f rep)-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @Bool) -> go reps (f rep)-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @Char) -> go reps (f rep)-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @Text) -> go reps (f rep)-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @ByteString) -> go reps (f rep)-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @ExitCode) -> go reps (f rep)-          | otherwise -> error $ "[OrdEqShow] type doesn't have enough instances " ++ show rep-    go (SomeTypeRep rep : reps) (Monadic f) =-      if-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @IO) -> go reps (f rep)-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @Maybe) -> go reps (f rep)-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @[]) -> go reps (f rep)-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @Tree) -> go reps (f rep)-          | Type.App either' _ <- rep,-            Just Type.HRefl <- Type.eqTypeRep either' (typeRep @Either) ->-              go reps (f rep)-          | otherwise -> error $ "[Monad] type doesn't have enough instances " ++ show rep-    go (SomeTypeRep rep : reps) (Applicable f) =-      if-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @IO) -> go reps (f rep)-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @Options.Parser) -> go reps (f rep)-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @Maybe) -> go reps (f rep)-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @[]) -> go reps (f rep)-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @Tree) -> go reps (f rep)-          | Type.App either' _ <- rep,-            Just Type.HRefl <- Type.eqTypeRep either' (typeRep @Either) ->-              go reps (f rep)-          | otherwise -> error $ "[Applicative] type doesn't have enough instances " ++ show rep-    go (SomeTypeRep rep : reps) (Monoidal f) =-      if-          | Type.App either' _ <- rep,-            Just Type.HRefl <- Type.eqTypeRep either' (typeRep @Vector) ->-              go reps (f rep)-          | Type.App (Type.App either' _) _ <- rep,-            Just Type.HRefl <- Type.eqTypeRep either' (typeRep @Options.Mod) ->-              go reps (f rep)-          | Type.App either' _ <- rep,-            Just Type.HRefl <- Type.eqTypeRep either' (typeRep @[]) ->-              go reps (f rep)-          | Just Type.HRefl <- Type.eqTypeRep rep (typeRep @Text) -> go reps (f rep)-          | otherwise -> error $ "[Monoid] type doesn't have enough instances " ++ show rep-    go reps (GetOf k0 a0 t0 r0 f) =-      case makeAccessor k0 r0 a0 t0 of-        Just accessor -> go reps (f accessor)-        Nothing -> error $ "missing field for field access"-    go reps (SetOf k0 a0 t0 r0 f) =-      case makeSetter k0 r0 a0 t0 of-        Just accessor -> go reps (f accessor)-        Nothing -> error $ "missing field for field set"-    go reps (ModifyOf k0 a0 t0 r0 f) =-      case makeModify k0 r0 a0 t0 of-        Just accessor -> go reps (f accessor)-        Nothing -> error $ "missing field for field modify"-    go tys r = error $ "forall type arguments mismatch: " ++ show tys ++ " for " ++ showR r-      where-        showR = \case-          NoClass {} -> "NoClass"-          SymbolOf {} -> "SymbolOf"-          StreamTypeOf {} -> "StreamTypeOf"-          ListOf {} -> "ListOf"-          OrdEqShow {} -> "OrdEqShow"-          Monadic {} -> "Monadic"-          Applicable {} -> "Applicable"-          Monoidal {} -> "Monoidal"-          GetOf {} -> "GetOf"-          SetOf {} -> "SetOf"-          ModifyOf {} -> "ModifyOf"-          Final {} -> "Final"---- Make a well-typed literal - e.g. @lit Text.length@ - which can be--- embedded in the untyped AST.-lookupVar :: String -> TyEnv g -> Either TypeCheckError (Typed (Var g))-lookupVar str Nil = Left $ NotInScope str-lookupVar v (Cons (Singleton s) ty e)-  | v == s = pure $ Typed ty (ZVar id)-  | otherwise = do-      Typed ty' v' <- lookupVar v e-      pure $ Typed ty' (SVar v')-lookupVar v (Cons (Tuple ss) ty e)-  | Just i <- lookup v $ zip ss [0 :: Int ..] =-      case ty of-        Type.App (Type.App tup x) y-          | Just Type.HRefl <- Type.eqTypeRep tup (typeRep @(,)) ->-              case i of-                0 -> pure $ Typed x $ ZVar \(a, _) -> a-                1 -> pure $ Typed y $ ZVar \(_, b) -> b-                _ -> Left TupleTypeMismatch-        Type.App (Type.App (Type.App tup x) y) z-          | Just Type.HRefl <- Type.eqTypeRep tup (typeRep @(,,)) ->-              case i of-                0 -> pure $ Typed x $ ZVar \(a, _, _) -> a-                1 -> pure $ Typed y $ ZVar \(_, b, _) -> b-                2 -> pure $ Typed z $ ZVar \(_, _, c) -> c-                _ -> Left TupleTypeMismatch-        Type.App (Type.App (Type.App (Type.App tup x) y) z) z'-          | Just Type.HRefl <- Type.eqTypeRep tup (typeRep @(,,,)) ->-              case i of-                0 -> pure $ Typed x $ ZVar \(a, _, _, _) -> a-                1 -> pure $ Typed y $ ZVar \(_, b, _, _) -> b-                2 -> pure $ Typed z $ ZVar \(_, _, c, _) -> c-                3 -> pure $ Typed z' $ ZVar \(_, _, _, d) -> d-                _ -> Left TupleTypeMismatch-        _ -> Left TupleTypeTooBig-  | otherwise = do-      Typed ty' v' <- lookupVar v e-      pure $ Typed ty' (SVar v')------------------------------------------------------------------------------------- Desugar expressions--data DesugarError-  = InvalidConstructor String-  | InvalidVariable String-  | UnknownType String-  | UnsupportedSyntax String-  | BadParameterSyntax String-  | KindError-  | BadDoNotation-  | TupleTooBig-  | UnsupportedLiteral-  deriving (Show, Eq)--nestedTyApps :: HSE.Exp HSE.SrcSpanInfo -> Maybe (HSE.QName HSE.SrcSpanInfo, [HSE.Type HSE.SrcSpanInfo])-nestedTyApps = go []-  where-    go acc (HSE.App _ (HSE.Var _ qname) (HSE.TypeApp _ ty)) = pure (qname, ty : acc)-    go acc (HSE.App _ (HSE.Con _ qname) (HSE.TypeApp _ ty)) = pure (qname, ty : acc)-    go acc (HSE.App _ e (HSE.TypeApp _ ty)) = go (ty : acc) e-    go _ _ = Nothing--desugarExp ::-  Map String SomeTypeRep ->-  Map String (UTerm ()) ->-  HSE.Exp HSE.SrcSpanInfo ->-  Either DesugarError (UTerm ())-desugarExp userDefinedTypeAliases globals = go mempty-  where-    go scope = \case-      HSE.Case l e alts -> do-        e' <- desugarCase l e alts-        go scope e'-      HSE.Paren _ x -> go scope x-      HSE.If l i t e ->-        (\e' t' i' -> UApp l () (UApp l () (UApp l () (bool' l) e') t') i')-          <$> go scope e-          <*> go scope t-          <*> go scope i-      HSE.Tuple l HSE.Boxed xs -> do-        xs' <- traverse (go scope) xs-        pure $ foldl (UApp l ()) (tuple' (length xs) l) xs'-      HSE.List l xs -> do-        xs' <- traverse (go scope) xs-        pure $ foldr (\x y -> UApp l () (UApp l () (cons' l) x) y) (nil' l) xs'-      HSE.Lit _ lit' -> case lit' of-        HSE.Char _ char _ -> pure $ lit char-        HSE.String _ string _ -> pure $ lit $ Text.pack string-        HSE.Int _ int _ -> pure $ lit (fromIntegral int :: Int)-        HSE.Frac _ _ str-          | Just dub <- Read.readMaybe str ->-              pure $ lit (dub :: Double)-        _ -> Left $ UnsupportedLiteral-      app@HSE.App {} | Just (qname, tys) <- nestedTyApps app -> do-        reps <- traverse (desugarSomeType userDefinedTypeAliases) tys-        desugarQName scope globals qname reps-      HSE.Var _ qname ->-        desugarQName scope globals qname []-      HSE.App l f x -> UApp l () <$> go scope f <*> go scope x-      HSE.InfixApp l x (HSE.QVarOp l'op f) y -> UApp l () <$> (UApp l'op () <$> go scope (HSE.Var l'op f) <*> go scope x) <*> go scope y-      HSE.Lambda l pats e -> do-        args <- traverse (desugarArg userDefinedTypeAliases) pats-        let stringArgs = concatMap (bindingStrings . fst) args-        e' <- go (foldr Set.insert scope stringArgs) e-        pure $ foldr (\(name, ty) inner -> ULam l () name ty inner) e' args-      HSE.Con _ qname ->-        desugarQName scope globals qname []-      HSE.Do _ stmts -> do-        let squash [HSE.Qualifier _ e] = pure e-            squash (s : ss) = do-              case s of-                HSE.Generator l pat e -> do-                  inner <- squash ss-                  let (.>>=) = HSE.Var l (HSE.Qual l (HSE.ModuleName l "Monad") (HSE.Ident l "bind"))-                  pure $-                    HSE.App-                      l-                      (HSE.App l (.>>=) e)-                      (HSE.Lambda l [pat] inner)-                HSE.Qualifier l e -> do-                  inner <- squash ss-                  let (.>>) = HSE.Var l (HSE.Qual l (HSE.ModuleName l "Monad") (HSE.Ident l "then"))-                  pure $-                    HSE.App-                      l-                      (HSE.App l (.>>) e)-                      inner-                HSE.LetStmt l (HSE.BDecls _ [HSE.PatBind _ pat (HSE.UnGuardedRhs _ e) Nothing]) -> do-                  inner <- squash ss-                  pure $ HSE.App l (HSE.Lambda l [pat] inner) e-                _ -> Left BadDoNotation-            squash _ = Left BadDoNotation-        squash stmts >>= go scope-      HSE.RecConstr _ qname fields -> go scope $ makeConstructRecord qname fields-      e -> Left $ UnsupportedSyntax $ show e---- Generates this:------ Variant.run---           x---           $ Variant.cons @"Main.Number" (\i -> Show.show i) $---              Variant.cons @"Main.Text" (\t -> t) $---                Variant.nil-desugarCase :: HSE.SrcSpanInfo -> HSE.Exp HSE.SrcSpanInfo -> [HSE.Alt HSE.SrcSpanInfo] -> Either DesugarError (HSE.Exp HSE.SrcSpanInfo)-desugarCase _ _ [] = Left $ UnsupportedSyntax "empty case"-desugarCase l scrutinee xs = do-  alts <- fmap (List.sortBy (Ord.comparing fst)) $ traverse desugarAlt xs-  pure $-    HSE.App l (HSE.App l run scrutinee) $-      foldr (HSE.App l) nil $-        map snd alts-  where-    tySym s = HSE.TyPromoted l (HSE.PromotedString l s s)-    nil =-      ( HSE.Var-          l-          ( hellQName l "NilA"-          )-      )-    run =-      ( HSE.Var-          l-          ( hellQName l "runAccessor")-      )-    desugarAlt-      ( HSE.Alt-          l'-          ( HSE.PApp-              _-              (HSE.UnQual _ (HSE.Ident _ name))-              [HSE.PVar _ (HSE.Ident _ x)]-            )-          (HSE.UnGuardedRhs _ e)-          _-        ) =-        -- Variant.cons @name (\x -> e)-        pure $-          (name,) $-            HSE.App-              l'-              ( HSE.App-                  l'-                  ( HSE.Var-                      l'-                      ( hellQName l' "ConsA")-                  )-                  (HSE.TypeApp l' (tySym name))-              )-              (HSE.Lambda l' [HSE.PVar l' (HSE.Ident l' x)] e)-    -- Nullary constructor-    desugarAlt-      ( HSE.Alt-          l'-          ( HSE.PApp-              _-              (HSE.UnQual _ (HSE.Ident _ name))-              []-            )-          (HSE.UnGuardedRhs _ e)-          _-        ) =-        -- Variant.cons @name (\_ -> e)-        pure $-          (name,) $-            HSE.App-              l'-              ( HSE.App-                  l'-                  ( HSE.Var-                      l'-                      ( hellQName l' "ConsA")-                  )-                  (HSE.TypeApp l' (tySym name))-              )-              (HSE.Lambda l' [HSE.PVar l' (HSE.Ident l' "_")] e)-    desugarAlt _ = Left $ UnsupportedSyntax "case alternative syntax"--bindingStrings :: Binding -> [String]-bindingStrings (Singleton string) = [string]-bindingStrings (Tuple tups) = tups--desugarQName :: Set String -> Map String (UTerm ()) -> HSE.QName HSE.SrcSpanInfo -> [SomeTypeRep] -> Either DesugarError (UTerm ())-desugarQName scope globals qname [] =-  case qname of-    HSE.UnQual _ (HSE.Ident l string) | Set.member string scope -> pure $ UVar l () string-    HSE.Qual _ (HSE.ModuleName _ "Main") (HSE.Ident _ string)-      | Just uterm <- Map.lookup string globals ->-          pure uterm-    HSE.Qual _ (HSE.ModuleName _ prefix) (HSE.Ident _ string)-      | Just (uterm, _) <- Map.lookup (prefix ++ "." ++ string) supportedLits ->-          pure $ uterm-    HSE.UnQual _ (HSE.Symbol _ string)-      | Just (uterm, _) <- Map.lookup string supportedLits ->-          pure $ uterm-    _ -> desugarPolyQName qname []-desugarQName _ _ qname treps = desugarPolyQName qname treps--desugarPolyQName :: HSE.QName HSE.SrcSpanInfo -> [SomeTypeRep] -> Either DesugarError (UTerm ())-desugarPolyQName qname treps =-  case qname of-    HSE.Qual l (HSE.ModuleName _ prefix) (HSE.Ident _ string)-      | Just (forall', vars, irep, _) <- Map.lookup (prefix ++ "." ++ string) polyLits -> do-          pure (UForall l () treps forall' vars irep [])-    HSE.UnQual l (HSE.Symbol _ string)-      | Just (forall', vars, irep, _) <- Map.lookup string polyLits -> do-          pure (UForall l () treps forall' vars irep [])-    HSE.Special l (HSE.UnitCon {}) ->-      pure $ litWithSpan l ()-    _ -> Left $ InvalidVariable $ show qname--desugarArg :: Map String SomeTypeRep -> HSE.Pat HSE.SrcSpanInfo -> Either DesugarError (Binding, Maybe SomeStarType)-desugarArg userDefinedTypeAliases (HSE.PatTypeSig _ (HSE.PVar _ (HSE.Ident _ i)) typ) =-  fmap (Singleton i,) (fmap Just (desugarStarType userDefinedTypeAliases typ))-desugarArg userDefinedTypeAliases (HSE.PatTypeSig _ (HSE.PTuple _ HSE.Boxed idents) typ)-  | Just idents' <- traverse desugarIdent idents =-      fmap (Tuple idents',) (fmap Just (desugarStarType userDefinedTypeAliases typ))-desugarArg _ (HSE.PVar _ (HSE.Ident _ i)) =-  pure (Singleton i, Nothing)-desugarArg _ (HSE.PTuple _ HSE.Boxed idents)-  | Just idents' <- traverse desugarIdent idents =-      pure (Tuple idents', Nothing)-desugarArg userDefinedTypeAliases (HSE.PParen _ p) = desugarArg userDefinedTypeAliases p-desugarArg _ p = Left $ BadParameterSyntax $ HSE.prettyPrint p--desugarIdent :: HSE.Pat HSE.SrcSpanInfo -> Maybe String-desugarIdent (HSE.PVar _ (HSE.Ident _ s)) = Just s-desugarIdent _ = Nothing------------------------------------------------------------------------------------- Desugar types--desugarStarType :: Map String SomeTypeRep -> HSE.Type HSE.SrcSpanInfo -> Either DesugarError SomeStarType-desugarStarType userDefinedTypeAliases t = do-  someRep <- desugarSomeType userDefinedTypeAliases t-  case someRep of-    StarTypeRep t' -> pure (SomeStarType t')-    _ -> Left KindError--desugarSomeType ::-  Map String SomeTypeRep ->-  HSE.Type HSE.SrcSpanInfo -> Either DesugarError SomeTypeRep-desugarSomeType userDefinedTypeAliases = go-  where-    go :: HSE.Type HSE.SrcSpanInfo -> Either DesugarError SomeTypeRep-    go = \case-      HSE.TyTuple _ HSE.Boxed types -> do-        tys <- traverse go types-        case tys of-          [StarTypeRep a, StarTypeRep b] ->-            pure $ StarTypeRep (Type.App (Type.App (typeRep @(,)) a) b)-          [StarTypeRep a, StarTypeRep b, StarTypeRep c] ->-            pure $ StarTypeRep (Type.App (Type.App (Type.App (typeRep @(,,)) a) b) c)-          [StarTypeRep a, StarTypeRep b, StarTypeRep c, StarTypeRep d] ->-            pure $ StarTypeRep (Type.App (Type.App (Type.App (Type.App (typeRep @(,,,)) a) b) c) d)-          _ -> Left TupleTooBig-      HSE.TyParen _ x -> go x-      HSE.TyCon _ (HSE.UnQual _ (HSE.Ident _ name))-        | Just rep <- Map.lookup name supportedTypeConstructors -> pure rep-      HSE.TyCon _ (HSE.Qual _ (HSE.ModuleName _ m) (HSE.Ident _ name))-        | Just rep <- Map.lookup (m <> "." <> name) (supportedTypeConstructors <> userDefinedTypeAliases) ->-            pure rep-      HSE.TyCon _ (HSE.Special _ HSE.UnitCon {}) -> pure $ StarTypeRep $ typeRep @()-      HSE.TyList _ inner -> do-        rep <- go inner-        case rep of-          StarTypeRep t' -> pure $ StarTypeRep $ Type.App (typeRep @[]) t'-          _ -> Left KindError-      HSE.TyFun _ a b -> do-        a' <- go a-        b' <- go b-        case (a', b') of-          (StarTypeRep aRep, StarTypeRep bRep) ->-            pure $ StarTypeRep (Type.Fun aRep bRep)-          _ -> Left KindError-      HSE.TyApp _ f a -> do-        f' <- go f-        a' <- go a-        case applyTypes f' a' of-          Just someTypeRep -> pure someTypeRep-          _ -> Left KindError-      HSE.TyPromoted _ (HSE.PromotedString _ string _) ->-        case someSymbolVal string of-          SomeSymbol p ->-            pure $ Type.someTypeRep p-      -- TODO: Remove later.-      HSE.TyPromoted _ (HSE.PromotedCon _ _bool (HSE.UnQual _ (HSE.Ident _ name)))-        | Just rep <- Map.lookup name supportedTypeConstructors -> pure rep-      t' -> Left $ UnknownType $ show t'---- | Apply a type `f' with an argument `x', if it is a type function,--- and the input is the right kind.-applyTypes :: SomeTypeRep -> SomeTypeRep -> Maybe SomeTypeRep-applyTypes (SomeTypeRep f) (SomeTypeRep x) =-  case Type.typeRepKind f of-    Type.App (Type.App (-->) a) _b-      | Just Type.HRefl <- Type.eqTypeRep (-->) (TypeRep @(->)) ->-          case Type.eqTypeRep (Type.typeRepKind x) a of-            Just Type.HRefl ->-              Just $ SomeTypeRep $ Type.App f x-            _ -> Nothing-    _ -> Nothing--desugarTypeSpec :: Spec-desugarTypeSpec = do-  it "desugarType" $ do-    shouldBe (try "Bool") (Right (SomeStarType $ typeRep @Bool))-    shouldBe (try "Int") (Right (SomeStarType $ typeRep @Int))-    shouldBe (try "Bool -> Int") (Right (SomeStarType $ typeRep @(Bool -> Int)))-    shouldBe (try "()") (Right (SomeStarType $ typeRep @()))-    shouldBe (try "[Int]") (Right (SomeStarType $ typeRep @[Int]))-  where-    try e = case fmap (desugarStarType mempty) $ HSE.parseType e of-      HSE.ParseOk r -> r-      _ -> error "Parse failed."------------------------------------------------------------------------------------- Desugar all bindings--desugarAll ::-  [(String, HSE.Type HSE.SrcSpanInfo)] ->-  [(String, HSE.Exp HSE.SrcSpanInfo)]-   -> Either DesugarError [(String, UTerm ())]-desugarAll types0 terms0 = do-  types <- flip execStateT Map.empty $-    traverse goType $ Graph.flattenSCCs $ stronglyConnected $ types0-  terms <- flip evalStateT Map.empty $-    traverse (goTerm types) $ Graph.flattenSCCs $ stronglyConnected $ terms0-  pure terms-  where-    goTerm ::-      Map String SomeTypeRep-      -> (String, HSE.Exp HSE.SrcSpanInfo)-      -> StateT (Map String (UTerm ())) (Either DesugarError) (String, UTerm ())-    goTerm userDefinedTypeAliases (name, expr) = do-      globals <- get-      uterm <- lift $ desugarExp userDefinedTypeAliases globals expr-      modify' $ Map.insert name uterm-      pure (name, uterm)--    goType ::-      (String, HSE.Type HSE.SrcSpanInfo)-      -> StateT (Map String SomeTypeRep) (Either DesugarError) ()-    goType (name, typ) = do-      types <- get-      SomeStarType someTypeRep <- lift $ desugarStarType types typ-      modify' $ Map.insert ("Main." ++ name) $ SomeTypeRep someTypeRep------------------------------------------------------------------------------------- Infer--data InferError-  = UnifyError UnifyError-  | ZonkError ZonkError-  | ElabError ElaborateError-  deriving (Show)---- | Note: All types in the input are free of metavars. There is an--- intermediate phase in which there are metavars, but then they're--- all eliminated. By the type system, the output contains only--- determinate types.-inferExp ::-  Map String (UTerm SomeTypeRep) ->-  UTerm () ->-  Either InferError (UTerm SomeTypeRep)-inferExp _ uterm =-  case elaborate uterm of-    Left elabError -> Left $ ElabError elabError-    Right (iterm, equalities) ->-      case unify equalities of-        Left unifyError -> Left $ UnifyError unifyError-        Right subs ->-          case traverse (zonkToStarType subs) iterm of-            Left zonkError -> Left $ ZonkError $ zonkError-            Right sterm -> pure sterm---- | Zonk a type and then convert it to a type: t :: *-zonkToStarType :: Map IMetaVar (IRep IMetaVar) -> IRep IMetaVar -> Either ZonkError SomeTypeRep-zonkToStarType subs irep = do-  zonked <- zonk (substitute subs irep)-  toSomeTypeRep zonked------------------------------------------------------------------------------------- Occurs check--anyCycles :: SYB.Data a => [(String, a)] -> Bool-anyCycles =-  any isCycle-    . stronglyConnected-  where-    isCycle = \case-      Graph.CyclicSCC {} -> True-      _ -> False--stronglyConnected :: SYB.Data a => [(String, a)] -> [Graph.SCC (String, a)]-stronglyConnected =-  Graph.stronglyConnComp-    . map \thing@(name, e) -> (thing, name, freeVariables e)--anyCyclesSpec :: Spec-anyCyclesSpec = do-  it "anyCycles" do-    shouldBe (try [("foo", "\\z -> x * Z.y"), ("bar", "\\z -> Main.bar * Z.y")]) True-    shouldBe (try [("foo", "\\z -> Main.bar * Z.y"), ("bar", "\\z -> Main.foo * Z.y")]) True-    shouldBe (try [("foo", "\\z -> x * Z.y"), ("bar", "\\z -> Main.mu * Z.y")]) False-    shouldBe (try [("foo", "\\z -> x * Z.y"), ("bar", "\\z -> Main.foo * Z.y")]) False-  where-    try named =-      case traverse (\(n, e) -> (n,) <$> HSE.parseExp e) named of-        HSE.ParseOk decls -> anyCycles decls-        _ -> error "Parse failed."------------------------------------------------------------------------------------- Get free variables of an HSE expression--freeVariables :: SYB.Data a => a -> [String]-freeVariables =-  Maybe.mapMaybe unpack-    . SYB.listify (const True :: HSE.QName HSE.SrcSpanInfo -> Bool)-  where-    unpack = \case-      HSE.Qual _ (HSE.ModuleName _ "Main") (HSE.Ident _ name) -> pure name-      _ -> Nothing--freeVariablesSpec :: Spec-freeVariablesSpec = do-  it "freeVariables" $ shouldBe (try "\\z -> Main.x * Z.y / Main.P") ["x", "P"]-  where-    try e = case fmap freeVariables $ HSE.parseExp e of-      HSE.ParseOk names -> names-      _ -> error "Parse failed."------------------------------------------------------------------------------------- Supported type constructors--supportedTypeConstructors :: Map String SomeTypeRep-supportedTypeConstructors =-  Map.fromList-    [-      -- Standard Haskell types-      ("Bool", SomeTypeRep $ typeRep @Bool),-      ("Int", SomeTypeRep $ typeRep @Int),-      ("Double", SomeTypeRep $ typeRep @Double),-      ("Char", SomeTypeRep $ typeRep @Char),-      ("Text", SomeTypeRep $ typeRep @Text),-      ("Map", SomeTypeRep $ typeRep @Map),-      ("ByteString", SomeTypeRep $ typeRep @ByteString),-      ("ExitCode", SomeTypeRep $ typeRep @ExitCode),-      ("Maybe", SomeTypeRep $ typeRep @Maybe),-      ("Either", SomeTypeRep $ typeRep @Either),-      ("IO", SomeTypeRep $ typeRep @IO),-      ("Vector", SomeTypeRep $ typeRep @Vector),-      ("Set", SomeTypeRep $ typeRep @Set),-      ("Tree", SomeTypeRep $ typeRep @Tree),-      ("Value", SomeTypeRep $ typeRep @Value),-      ("()", SomeTypeRep $ typeRep @()),--      -- Internal, hidden types-      ("hell:Hell.NilL", SomeTypeRep $ typeRep @('NilL)),-      ("hell:Hell.ConsL", SomeTypeRep $ typeRep @('ConsL)),-      ("hell:Hell.Variant", SomeTypeRep $ typeRep @Variant),-      ("hell:Hell.Record", SomeTypeRep $ typeRep @Record),-      ("hell:Hell.Tagged", SomeTypeRep $ typeRep @Tagged),-      ("hell:Hell.Nullary", SomeTypeRep $ typeRep @Nullary)-    ]---- | Used for constructors with no slot. E.g. True :: Nullary -> Bool-data Nullary = Nullary------------------------------------------------------------------------------------- Support primitives--supportedLits :: Map String (UTerm (), SomeTypeRep)-supportedLits =-  Map.fromList-    [ -- Text I/O-      ("Text.putStrLn", lit' t_putStrLn),-      ("Text.hPutStr", lit' t_hPutStr),-      ("Text.putStr", lit' t_putStr),-      ("Text.getLine", lit' t_getLine),-      ("Text.writeFile", lit' t_writeFile),-      ("Text.readFile", lit' t_readFile),-      ("Text.appendFile", lit' t_appendFile),-      ("Text.readProcess", lit' t_readProcess),-      ("Text.readProcess_", lit' t_readProcess_),-      ("Text.readProcessStdout_", lit' t_readProcessStdout_),-      ("Text.getContents", lit' (fmap Text.decodeUtf8 ByteString.getContents)),-      ("Text.setStdin", lit' t_setStdin),-      -- Text operations-      ("Text.decodeUtf8", lit' Text.decodeUtf8),-      ("Text.encodeUtf8", lit' Text.encodeUtf8),-      ("Text.eq", lit' ((==) @Text)),-      ("Text.length", lit' Text.length),-      ("Text.concat", lit' Text.concat),-      ("Text.breakOn", lit' Text.breakOn),-      ("Text.lines", lit' Text.lines),-      ("Text.words", lit' Text.words),-      ("Text.unlines", lit' Text.unlines),-      ("Text.unwords", lit' Text.unwords),-      ("Text.intercalate", lit' Text.intercalate),-      ("Text.reverse", lit' Text.reverse),-      ("Text.toLower", lit' Text.toLower),-      ("Text.toUpper", lit' Text.toUpper),-      -- Needs Char operations.-      -- ("Text.any", lit' Text.any),-      -- ("Text.all", lit' Text.all),-      -- ("Text.filter", lit' Text.filter),-      ("Text.take", lit' Text.take),-      ("Text.splitOn", lit' Text.splitOn),-      ("Text.takeEnd", lit' Text.takeEnd),-      ("Text.drop", lit' Text.drop),-      ("Text.stripPrefix", lit' Text.stripPrefix),-      ("Text.stripSuffix", lit' Text.stripSuffix),-      ("Text.isSuffixOf", lit' Text.isSuffixOf),-      ("Text.isPrefixOf", lit' Text.isPrefixOf),-      ("Text.dropEnd", lit' Text.dropEnd),-      ("Text.strip", lit' Text.strip),-      ("Text.replace", lit' Text.replace),-      ("Text.isPrefixOf", lit' Text.isPrefixOf),-      ("Text.isSuffixOf", lit' Text.isSuffixOf),-      ("Text.isInfixOf", lit' Text.isInfixOf),-      ("Text.interact", lit' (\f -> ByteString.interact (Text.encodeUtf8 . f . Text.decodeUtf8))),-      -- Int operations-      ("Int.show", lit' (Text.pack . show @Int)),-      ("Int.eq", lit' ((==) @Int)),-      ("Int.plus", lit' ((+) @Int)),-      ("Int.mult", lit' ((*) @Int)),-      ("Int.subtract", lit' (subtract @Int)),-      -- Double operations-      ("Double.fromInt", lit' (fromIntegral :: Int -> Double)),-      ("Double.show", lit' (Text.pack . show @Double)),-      ("Double.eq", lit' ((==) @Double)),-      ("Double.plus", lit' ((+) @Double)),-      ("Double.mult", lit' ((*) @Double)),-      ("Double.subtract", lit' (subtract @Double)),-      -- Bytes I/O-      ("ByteString.hGet", lit' ByteString.hGet),-      ("ByteString.hPutStr", lit' ByteString.hPutStr),-      ("ByteString.writeFile", lit' bytestring_writeFile),-      ("ByteString.readFile", lit' bytestring_readFile),-      ("ByteString.readProcess", lit' b_readProcess),-      ("ByteString.readProcess_", lit' b_readProcess_),-      ("ByteString.readProcessStdout_", lit' b_readProcessStdout_),-      ("ByteString.interact", lit' ByteString.interact),-      ("ByteString.getContents", lit' ByteString.getContents),-      -- Handles, buffering-      ("IO.stdout", lit' IO.stdout),-      ("IO.stderr", lit' IO.stderr),-      ("IO.stdin", lit' IO.stdin),-      ("IO.hSetBuffering", lit' IO.hSetBuffering),-      ("IO.NoBuffering", lit' IO.NoBuffering),-      ("IO.LineBuffering", lit' IO.LineBuffering),-      ("IO.BlockBuffering", lit' IO.BlockBuffering),-      ("IO.hClose", lit' IO.hClose),-      ("IO.openFile", lit' (\f m -> IO.openFile (Text.unpack f) m)),-      ("IO.ReadMode", lit' IO.ReadMode),-      ("IO.WriteMode", lit' IO.WriteMode),-      ("IO.AppendMode", lit' IO.AppendMode),-      ("IO.ReadWriteMode", lit' IO.ReadWriteMode),-      -- Concurrent stuff-      ("Concurrent.threadDelay", lit' Concurrent.threadDelay),-      -- Bool-      ("Bool.True", lit' Bool.True),-      ("Bool.False", lit' Bool.False),-      ("Bool.not", lit' Bool.not),-      -- Get arguments-      ("Environment.getArgs", lit' $ fmap (map Text.pack) getArgs),-      ("Environment.getEnvironment", lit' $ fmap (map (bimap Text.pack Text.pack)) getEnvironment),-      ("Environment.getEnv", lit' $ fmap Text.pack . getEnv . Text.unpack),-      -- Current directory-      ("Directory.createDirectoryIfMissing", lit' (\b f -> Dir.createDirectoryIfMissing b (Text.unpack f))),-      ("Directory.createDirectory", lit' (Dir.createDirectory . Text.unpack)),-      ("Directory.getCurrentDirectory", lit' (fmap Text.pack Dir.getCurrentDirectory)),-      ("Directory.listDirectory", lit' (fmap (fmap Text.pack) . Dir.listDirectory . Text.unpack)),-      ("Directory.setCurrentDirectory", lit' (Dir.setCurrentDirectory . Text.unpack)),-      ("Directory.renameFile", lit' (\x y -> Dir.renameFile (Text.unpack x) (Text.unpack y))),-      ("Directory.copyFile", lit' (\x y -> Dir.copyFile (Text.unpack x) (Text.unpack y))),-      ("Directory.removeFile", lit' (\x -> Dir.removeFile (Text.unpack x))),-      -- Process-      ("Process.proc", lit' $ \n xs -> proc (Text.unpack n) (map Text.unpack xs)),-      ("Process.setEnv", lit' $ Process.setEnv @() @() @() . map (bimap Text.unpack Text.unpack)),--      -- Exit-      ("Exit.ExitSuccess", lit' Exit.ExitSuccess),-      ("Exit.ExitFailure", lit' Exit.ExitFailure),-      -- Lists-      ("List.and", lit' (List.and @[])),-      ("List.or", lit' (List.or @[])),-      -- Json-      ("Json.decode", lit' (Json.decode . L.fromStrict :: ByteString -> Maybe Value)),-      ("Json.encode", lit' (L.toStrict . Json.encode :: Value -> ByteString)),-      ("Json.Number", lit' (Json.toJSON :: Double -> Value)),-      ("Json.String", lit' (Json.toJSON :: Text -> Value)),-      ("Json.Bool", lit' (Json.toJSON :: Bool -> Value)),-      ("Json.Null", lit' Json.Null),-      ("Json.Array", lit' (Json.toJSON :: Vector Value -> Value)),-      ("Json.Object", lit' (Json.toJSON :: Map Text Value -> Value)),-      -- Records-      ("hell:Hell.NilR", lit' NilR),-      -- Nullary-      ("hell:Hell.Nullary", lit' Nullary),-      -- Options-      ("Options.switch", lit' Options.switch),-      ("Options.strOption", lit' (Options.strOption @Text)),-      ("Options.strArgument", lit' (Options.strArgument @Text))-    ]-  where-    lit' :: forall a. (Type.Typeable a) => a -> (UTerm (), SomeTypeRep)-    lit' x = (lit x, SomeTypeRep $ Type.typeOf x)------------------------------------------------------------------------------------- Derive prims TH--polyLits :: Map String (Forall, [TH.Uniq], IRep TH.Uniq, TH.Type)-polyLits =-  Map.fromList-    $( let -- Derive well-typed primitive forms.-           derivePrims :: Q TH.Exp -> Q TH.Exp-           derivePrims m = do-             e <- m-             case e of-               TH.DoE Nothing binds -> do-                 TH.listE $ map makePrim binds-               _ -> error $ "Expected plain do-notation, but got: " ++ show e--           nameUnique (TH.Name _ (TH.NameU i)) = i-           nameUnique _ = error "Bad TH problem in nameUnique."--           toTy :: TH.Type -> Q TH.Exp-           toTy = \case-             TH.AppT (TH.AppT TH.ArrowT f) x -> [|IFun $(toTy f) $(toTy x)|]-             TH.AppT f x -> [|IApp $(toTy f) $(toTy x)|]-             TH.ConT name -> [|ICon (SomeTypeRep $(TH.appTypeE (TH.varE 'typeRep) (TH.conT name)))|]-             TH.VarT a -> [|IVar $(TH.litE $ TH.IntegerL $ nameUnique a)|]-             TH.ListT -> [|ICon (SomeTypeRep (typeRep @[]))|]-             TH.TupleT 2 -> [|ICon (SomeTypeRep (typeRep @(,)))|]-             TH.TupleT 3 -> [|ICon (SomeTypeRep (typeRep @(,,)))|]-             TH.TupleT 4 -> [|ICon (SomeTypeRep (typeRep @(,,,)))|]-             TH.TupleT 0 -> [|ICon (SomeTypeRep (typeRep @()))|]-             ty@TH.PromotedT {} -> [|ICon (SomeTypeRep $(TH.appTypeE (TH.varE 'typeRep) (pure ty)))|]-             t -> error $ "Unexpected type shape: " ++ show t--           -- Make a well-typed primitive form. Expects a very strict format.-           makePrim :: TH.Stmt -> Q TH.Exp-           makePrim-             ( TH.NoBindS-                 ( TH.SigE-                     (TH.AppE (TH.LitE (TH.StringL string)) expr0)-                     thtype@(TH.ForallT vars constraints typ)-                   )-               ) =-               let constrained = foldl getConstraint mempty constraints-                   vars0 =-                     map-                       ( \case-                           (TH.PlainTV v TH.SpecifiedSpec) -> TH.litE $ TH.IntegerL $ nameUnique v-                           (TH.KindedTV v TH.SpecifiedSpec _k) -> TH.litE $ TH.IntegerL $ nameUnique v-                           _ -> error "The type variable isn't what I expected."-                       )-                       vars-                   vars0T =-                     map-                       ( \case-                           (TH.PlainTV v TH.SpecifiedSpec) -> TH.varT v-                           (TH.KindedTV v TH.SpecifiedSpec _k) -> TH.varT v-                           _ -> error "The type variable isn't what I expected."-                       )-                       vars-                   ordEqShow = Set.fromList [''Ord, ''Eq, ''Show]-                   monadics = Set.fromList [''Monad]-                   -- When we add a type that is a Functor but not an-                   -- Applicative, we should add a Functor class or-                   -- this will try to raise it to an Applicative.-                   applicables = Set.fromList [''Functor, ''Applicative]-                   monoidals = Set.fromList [''Semigroup, ''Monoid]-                   finalExpr =-                     if-                         | string == "Record.get" ->-                             [|-                               GetOf-                                 (TypeRep @($(vars0T !! 0)))-                                 (TypeRep @($(vars0T !! 1)))-                                 (TypeRep @($(vars0T !! 2)))-                                 (TypeRep @($(vars0T !! 3)))-                                 \getter -> Final $ typed $(TH.sigE (TH.varE 'getter) (pure typ))-                               |]-                         | string == "Record.set" ->-                             [|-                               SetOf-                                 (TypeRep @($(vars0T !! 0)))-                                 (TypeRep @($(vars0T !! 1)))-                                 (TypeRep @($(vars0T !! 2)))-                                 (TypeRep @($(vars0T !! 3)))-                                 \setter -> Final $ typed $(TH.sigE (TH.varE 'setter) (pure typ))-                               |]-                         | string == "Record.modify" ->-                             [|-                               ModifyOf-                                 (TypeRep @($(vars0T !! 0)))-                                 (TypeRep @($(vars0T !! 1)))-                                 (TypeRep @($(vars0T !! 2)))-                                 (TypeRep @($(vars0T !! 3)))-                                 \modif -> Final $ typed $(TH.sigE (TH.varE 'modif) (pure typ))-                               |]-                         | otherwise -> [|Final $ typed $(TH.sigE (pure expr0) (pure typ))|]-                   builder =-                     foldr-                       ( \case-                           (TH.PlainTV v TH.SpecifiedSpec) -> \rest ->-                             TH.appE-                               ( TH.conE-                                   ( case Map.lookup v constrained of-                                       Nothing -> 'NoClass-                                       Just constraints'-                                         | Set.isSubsetOf constraints' ordEqShow -> 'OrdEqShow-                                         | Set.isSubsetOf constraints' monadics -> 'Monadic-                                         | Set.isSubsetOf constraints' applicables -> 'Applicable-                                         | Set.isSubsetOf constraints' monoidals -> 'Monoidal-                                       _ -> error "I'm not sure what to do with this variable."-                                   )-                               )-                               ( TH.lamE-                                   [pure $ TH.ConP 'TypeRep [TH.VarT v] []]-                                   rest-                               )-                           (TH.KindedTV v TH.SpecifiedSpec (TH.ConT v_k)) | v_k == ''Symbol -> \rest ->-                             TH.appE-                               (TH.conE 'SymbolOf)-                               ( TH.lamE-                                   [pure $ TH.ConP 'TypeRep [TH.SigT (TH.VarT v) (TH.ConT v_k)] []]-                                   rest-                               )-                           (TH.KindedTV v TH.SpecifiedSpec (TH.ConT v_k)) | v_k == ''List -> \rest ->-                             TH.appE-                               (TH.conE 'ListOf)-                               ( TH.lamE-                                   [pure $ TH.ConP 'TypeRep [TH.SigT (TH.VarT v) (TH.ConT v_k)] []]-                                   rest-                               )-                           (TH.KindedTV v TH.SpecifiedSpec (TH.ConT v_k)) | v_k == ''StreamType -> \rest ->-                             TH.appE-                               (TH.conE 'StreamTypeOf)-                               ( TH.lamE-                                   [pure $ TH.ConP 'TypeRep [TH.SigT (TH.VarT v) (TH.ConT v_k)] []]-                                   rest-                               )-                           t -> error $ "Did not expect this type of variable! " ++ show t-                       )-                       finalExpr-                       vars-                in [|(string, ($builder, $(TH.listE vars0), $(toTy typ), thtype))|]-           makePrim e = error $ "Should be of the form \"Some.name\" The.name :: T\ngot: " ++ show e--           -- Just tells us whether a given variable is constrained by a-           -- type-class or not.-           getConstraint m (TH.AppT (TH.ConT cls') (TH.VarT v)) =-             Map.insertWith Set.union v (Set.singleton cls') m-           getConstraint _ _ = error "Bad constraint!"-        in derivePrims-             [|-               do-                 -- Records-                 "hell:Hell.ConsR" ConsR :: forall (k :: Symbol) a (xs :: List). a -> Record xs -> Record (ConsL k a xs)-                 "Record.get" _ :: forall (k :: Symbol) a (t :: Symbol) (xs :: List). Tagged t (Record xs) -> a-                 "Record.set" _ :: forall (k :: Symbol) a (t :: Symbol) (xs :: List). a -> Tagged t (Record xs) -> Tagged t (Record xs)-                 "Record.modify" _ :: forall (k :: Symbol) a (t :: Symbol) (xs :: List). (a -> a) -> Tagged t (Record xs) -> Tagged t (Record xs)-                 -- Variants-                 "hell:Hell.LeftV" LeftV :: forall (k :: Symbol) a (xs :: List). a -> Variant (ConsL k a xs)-                 "hell:Hell.RightV" RightV :: forall (k :: Symbol) a (xs :: List) (k'' :: Symbol) a''. Variant (ConsL k'' a'' xs) -> Variant (ConsL k a (ConsL k'' a'' xs))-                 "hell:Hell.NilA" NilA :: forall r. Accessor 'NilL r-                 "hell:Hell.ConsA" ConsA :: forall (k :: Symbol) a r (xs :: List). (a -> r) -> Accessor xs r -> Accessor (ConsL k a xs) r-                 "hell:Hell.runAccessor" runAccessor :: forall (t :: Symbol) r (xs :: List). Tagged t (Variant xs) -> Accessor xs r -> r-                 -- Tagged-                 "hell:Hell.Tagged" Tagged :: forall (t :: Symbol) a. a -> Tagged t a-                 -- Functor-                 "Functor.fmap" fmap :: forall f a b. Functor f => (a -> b) -> f a -> f b-                 -- Operators-                 "$" (Function.$) :: forall a b. (a -> b) -> a -> b-                 "." (Function..) :: forall a b c. (b -> c) -> (a -> b) -> a -> c-                 "<>" (<>) :: forall m. Semigroup m => m -> m -> m-                 -- Monad-                 "Monad.bind" (Prelude.>>=) :: forall m a b. (Monad m) => m a -> (a -> m b) -> m b-                 "Monad.then" (Prelude.>>) :: forall m a b. (Monad m) => m a -> m b -> m b-                 "Monad.return" return :: forall a m. (Monad m) => a -> m a-                 -- Applicative operations-                 "Applicative.pure" pure :: forall f a. Applicative f => a -> f a-                 "<*>" (<*>) :: forall f a b. Applicative f => f (a -> b) -> f a -> f b-                 "<$>" (<$>) :: forall f a b. Functor f => (a -> b) -> f a -> f b-                 "<**>" (Options.<**>) :: forall f a b. Applicative f => f a -> f (a -> b) -> f b-                 -- Monadic operations-                 "Monad.mapM_" mapM_ :: forall a m. (Monad m) => (a -> m ()) -> [a] -> m ()-                 "Monad.forM_" forM_ :: forall a m. (Monad m) => [a] -> (a -> m ()) -> m ()-                 "Monad.mapM" mapM :: forall a b m. (Monad m) => (a -> m b) -> [a] -> m [b]-                 "Monad.forM" forM :: forall a b m. (Monad m) => [a] -> (a -> m b) -> m [b]-                 "Monad.when" when :: forall m. (Monad m) => Bool -> m () -> m ()-                 -- IO-                 "IO.mapM_" mapM_ :: forall a. (a -> IO ()) -> [a] -> IO ()-                 "IO.forM_" forM_ :: forall a. [a] -> (a -> IO ()) -> IO ()-                 "IO.pure" pure :: forall a. a -> IO a-                 "IO.print" (t_putStrLn . Text.pack . Show.show) :: forall a. (Show a) => a -> IO ()-                 "Timeout.timeout" Timeout.timeout :: forall a. Int -> IO a -> IO (Maybe a)-                 -- Show-                 "Show.show" (Text.pack . Show.show) :: forall a. (Show a) => a -> Text-                 -- Eq/Ord-                 "Eq.eq" (Eq.==) :: forall a. (Eq a) => a -> a -> Bool-                 "Ord.lt" (Ord.<) :: forall a. (Ord a) => a -> a -> Bool-                 "Ord.gt" (Ord.>) :: forall a. (Ord a) => a -> a -> Bool-                 -- Tuples-                 "Tuple.(,)" (,) :: forall a b. a -> b -> (a, b)-                 "Tuple.(,)" (,) :: forall a b. a -> b -> (a, b)-                 "Tuple.(,,)" (,,) :: forall a b c. a -> b -> c -> (a, b, c)-                 "Tuple.(,,,)" (,,,) :: forall a b c d. a -> b -> c -> d -> (a, b, c, d)-                 -- Exit-                 "Exit.die" (Exit.die . Text.unpack) :: forall a. Text -> IO a-                 "Exit.exitWith" Exit.exitWith :: forall a. ExitCode -> IO a-                 "Exit.exitCode" exit_exitCode :: forall a. a -> (Int -> a) -> ExitCode -> a-                 -- Exceptions-                 "Error.error" (error . Text.unpack) :: forall a. Text -> a-                 -- Bool-                 "Bool.bool" Bool.bool :: forall a. a -> a -> Bool -> a-                 -- Function-                 "Function.id" Function.id :: forall a. a -> a-                 "Function.fix" Function.fix :: forall a. (a -> a) -> a-                 -- Set-                 "Set.fromList" Set.fromList :: forall a. (Ord a) => [a] -> Set a-                 "Set.insert" Set.insert :: forall a. (Ord a) => a -> Set a -> Set a-                 "Set.member" Set.member :: forall a. (Ord a) => a -> Set a -> Bool-                 "Set.delete" Set.delete :: forall a. (Ord a) => a -> Set a -> Set a-                 "Set.union" Set.union :: forall a. (Ord a) => Set a -> Set a -> Set a-                 "Set.difference" Set.difference :: forall a. (Ord a) => Set a -> Set a -> Set a-                 "Set.intersection" Set.intersection :: forall a. (Ord a) => Set a -> Set a -> Set a-                 "Set.toList" Set.toList :: forall a. Set a -> [a]-                 "Set.size" Set.size :: forall a. Set a -> Int-                 "Set.singleton" Set.singleton :: forall a. (Ord a) => a -> Set a-                 -- Trees-                 "Tree.Node" Tree.Node :: forall a. a -> [Tree a] -> Tree a-                 "Tree.unfoldTree" Tree.unfoldTree :: forall a b. (b -> (a, [b])) -> b -> Tree a-                 "Tree.foldTree" Tree.foldTree :: forall a b. (a -> [b] -> b) -> Tree a -> b-                 "Tree.flatten" Tree.flatten :: forall a. Tree a -> [a]-                 "Tree.levels" Tree.levels :: forall a. Tree a -> [[a]]-                 "Tree.map" fmap :: forall a b. (a -> b) -> Tree a -> Tree b-                 -- Lists-                 "List.cons" (:) :: forall a. a -> [a] -> [a]-                 "List.nil" [] :: forall a. [a]-                 "List.length" List.length :: forall a. [a] -> Int-                 "List.scanl'" List.scanl' :: forall a b. (b -> a -> b) -> b -> [a] -> [b]-                 "List.scanr" List.scanr :: forall a b. (a -> b -> b) -> b -> [a] -> [b]-                 "List.concat" List.concat :: forall a. [[a]] -> [a]-                 "List.concatMap" List.concatMap :: forall a b. (a -> [b]) -> [a] -> [b]-                 "List.drop" List.drop :: forall a. Int -> [a] -> [a]-                 "List.take" List.take :: forall a. Int -> [a] -> [a]-                 "List.splitAt" List.splitAt :: forall a. Int -> [a] -> ([a], [a])-                 "List.break" List.break :: forall a. (a -> Bool) -> [a] -> ([a], [a])-                 "List.span" List.span :: forall a. (a -> Bool) -> [a] -> ([a], [a])-                 "List.partition" List.partition :: forall a. (a -> Bool) -> [a] -> ([a], [a])-                 "List.takeWhile" List.takeWhile :: forall a. (a -> Bool) -> [a] -> [a]-                 "List.dropWhile" List.dropWhile :: forall a. (a -> Bool) -> [a] -> [a]-                 "List.dropWhileEnd" List.dropWhileEnd :: forall a. (a -> Bool) -> [a] -> [a]-                 "List.map" List.map :: forall a b. (a -> b) -> [a] -> [b]-                 "List.any" List.any :: forall a. (a -> Bool) -> [a] -> Bool-                 "List.all" List.all :: forall a. (a -> Bool) -> [a] -> Bool-                 "List.iterate'" List.iterate' :: forall a. (a -> a) -> a -> [a]-                 "List.repeat" List.repeat :: forall a. a -> [a]-                 "List.cycle" List.cycle :: forall a. [a] -> [a]-                 "List.filter" List.filter :: forall a. (a -> Bool) -> [a] -> [a]-                 "List.foldl'" List.foldl' :: forall a b. (b -> a -> b) -> b -> [a] -> b-                 "List.foldr" List.foldr :: forall a b. (a -> b -> b) -> b -> [a] -> b-                 "List.unfoldr" List.unfoldr :: forall a b. (b -> Maybe (a, b)) -> b -> [a]-                 "List.zip" List.zip :: forall a b. [a] -> [b] -> [(a, b)]-                 "List.mapAccumL" List.mapAccumL :: forall s a b. (s -> a -> (s, b)) -> s -> [a] -> (s, [b])-                 "List.mapAccumR" List.mapAccumL :: forall s a b. (s -> a -> (s, b)) -> s -> [a] -> (s, [b])-                 "List.zipWith" List.zipWith :: forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]-                 "List.lookup" List.lookup :: forall a b. (Eq a) => a -> [(a, b)] -> Maybe b-                 "List.find" List.find :: forall a. (a -> Bool) -> [a] -> Maybe a-                 "List.sort" List.sort :: forall a. (Ord a) => [a] -> [a]-                 "List.group" List.group :: forall a. (Eq a) => [a] -> [[a]]-                 "List.isPrefixOf" List.isPrefixOf :: forall a. (Eq a) => [a] -> [a] -> Bool-                 "List.isSuffixOf" List.isSuffixOf :: forall a. (Eq a) => [a] -> [a] -> Bool-                 "List.isInfixOf" List.isInfixOf :: forall a. (Eq a) => [a] -> [a] -> Bool-                 "List.isSubsequenceOf" List.isSubsequenceOf :: forall a. (Eq a) => [a] -> [a] -> Bool-                 "List.groupBy" List.groupBy :: forall a. (a -> a -> Bool) -> [a] -> [[a]]-                 "List.reverse" List.reverse :: forall a. [a] -> [a]-                 "List.nubOrd" nubOrd :: forall a. (Ord a) => [a] -> [a]-                 "List.inits" List.inits :: forall a. [a] -> [[a]]-                 "List.tails" List.tails :: forall a. [a] -> [[a]]-                 "List.deleteBy" List.deleteBy :: forall a. (a -> a -> Bool) -> a -> [a] -> [a]-                 "List.elem" List.elem :: forall a. (Eq a) => a -> [a] -> Bool-                 "List.notElem" List.notElem :: forall a. (Eq a) => a -> [a] -> Bool-                 "List.sortOn" List.sortOn :: forall a b. (Ord b) => (a -> b) -> [a] -> [a]-                 "List.null" List.null :: forall a. [a] -> Bool-                 "List.elemIndex" List.elemIndex :: forall a. (Eq a) => a -> [a] -> Maybe Int-                 "List.elemIndices" List.elemIndices :: forall a. (Eq a) => a -> [a] -> [Int]-                 "List.findIndex" List.findIndex :: forall a. (a -> Bool) -> [a] -> Maybe Int-                 "List.findIndices" List.findIndices :: forall a. (a -> Bool) -> [a] -> [Int]-                 "List.uncons" List.uncons :: forall a. [a] -> Maybe (a, [a])-                 "List.intersperse" List.intersperse :: forall a. a -> [a] -> [a]-                 "List.intercalate" List.intercalate :: forall a. [a] -> [[a]] -> [a]-                 "List.transpose" List.transpose :: forall a. [[a]] -> [[a]]-                 "List.subsequences" List.subsequences :: forall a. [a] -> [[a]]-                 "List.permutations" List.permutations :: forall a. [a] -> [[a]]-                 -- Vector-                 "Vector.fromList" Vector.fromList :: forall a. [a] -> Vector a-                 "Vector.toList" Vector.toList :: forall a. Vector a -> [a]-                 -- Map-                 "Map.fromList" Map.fromList :: forall k a. (Ord k) => [(k, a)] -> Map k a-                 "Map.lookup" Map.lookup :: forall k a. (Ord k) => k -> Map k a -> Maybe a-                 "Map.insert" Map.insert :: forall k a. (Ord k) => k -> a -> Map k a -> Map k a-                 "Map.delete" Map.delete :: forall k a. (Ord k) => k -> Map k a -> Map k a-                 "Map.singleton" Map.singleton :: forall k a. (Ord k) => k -> a -> Map k a-                 "Map.size" Map.size :: forall k a. Map k a -> Int-                 "Map.filter" Map.filter :: forall k a. (a -> Bool) -> Map k a -> Map k a-                 "Map.filterWithKey" Map.filterWithKey :: forall k a. (k -> a -> Bool) -> Map k a -> Map k a-                 "Map.any" any :: forall k a. (a -> Bool) -> Map k a -> Bool-                 "Map.all" all :: forall k a. (a -> Bool) -> Map k a -> Bool-                 "Map.insertWith" Map.insertWith :: forall k a. (Ord k) => (a -> a -> a) -> k -> a -> Map k a -> Map k a-                 "Map.adjust" Map.adjust :: forall k a. (Ord k) => (a -> a) -> k -> Map k a -> Map k a-                 "Map.unionWith" Map.unionWith :: forall k a. (Ord k) => (a -> a -> a) -> Map k a -> Map k a -> Map k a-                 "Map.map" Map.map :: forall a b k. (a -> b) -> Map k a -> Map k b-                 "Map.toList" Map.toList :: forall k a. Map k a -> [(k, a)]-                 "Map.keys" Map.keys :: forall k a. Map k a -> [k]-                 "Map.elems" Map.elems :: forall k a. Map k a -> [a]-                 -- Maybe-                 "Maybe.maybe" Maybe.maybe :: forall a b. b -> (a -> b) -> Maybe a -> b-                 "Maybe.Nothing" Maybe.Nothing :: forall a. Maybe a-                 "Maybe.Just" Maybe.Just :: forall a. a -> Maybe a-                 "Maybe.listToMaybe" Maybe.listToMaybe :: forall a. [a] -> Maybe a-                 "Maybe.mapMaybe" Maybe.mapMaybe :: forall a b. (a -> Maybe b) -> [a] -> [b]-                 -- Either-                 "Either.either" Either.either :: forall a b x. (a -> x) -> (b -> x) -> Either a b -> x-                 "Either.Left" Either.Left :: forall a b. a -> Either a b-                 "Either.Right" Either.Right :: forall a b. b -> Either a b-                 -- Async-                 "Async.concurrently" Async.concurrently :: forall a b. IO a -> IO b -> IO (a, b)-                 "Async.race" Async.race :: forall a b. IO a -> IO b -> IO (Either a b)-                 "Async.pooledMapConcurrently_" Async.pooledMapConcurrently_ :: forall a. (a -> IO ()) -> [a] -> IO ()-                 "Async.pooledForConcurrently_" Async.pooledForConcurrently_ :: forall a. [a] -> (a -> IO ()) -> IO ()-                 "Async.pooledMapConcurrently" Async.pooledMapConcurrently :: forall a b. (a -> IO b) -> [a] -> IO [b]-                 "Async.pooledForConcurrently" Async.pooledForConcurrently :: forall a b. [a] -> (a -> IO b) -> IO [b]-                 -- JSON-                 "Json.value" json_value :: forall a. a -> (Bool -> a) -> (Text -> a) -> (Double -> a) -> (Vector Value -> a) -> (Map Text Value -> a) -> Value -> a-                 -- Temp-                 "Temp.withSystemTempFile" temp_withSystemTempFile :: forall a. Text -> (Text -> IO.Handle -> IO a) -> IO a-                 "Temp.withSystemTempDirectory" temp_withSystemTempDirectory :: forall a. Text -> (Text -> IO a) -> IO a-                 -- Process-                 "Process.runProcess" runProcess :: forall a b c. ProcessConfig a b c -> IO ExitCode-                 "Process.runProcess_" runProcess_ :: forall a b c. ProcessConfig a b c -> IO ()-                 "Process.setStdout" setStdout :: forall stdin stdout stdout' stderr. StreamSpec 'STOutput stdout' -> ProcessConfig stdin stdout stderr -> ProcessConfig stdin stdout' stderr-                 "Process.useHandleClose" useHandleClose :: forall (a :: StreamType). IO.Handle -> StreamSpec a ()-                 "Process.useHandleOpen" useHandleOpen :: forall (a :: StreamType). IO.Handle -> StreamSpec a ()-                 "Process.setWorkingDir" process_setWorkingDir :: forall a b c. Text -> ProcessConfig a b c -> ProcessConfig a b c-                 -- Options-                 "Options.execParser" Options.execParser :: forall a. Options.ParserInfo a -> IO a-                 "Options.info" Options.info :: forall a. Options.Parser a -> Options.InfoMod a -> Options.ParserInfo a-                 "Options.helper" Options.helper :: forall a. Options.Parser (a -> a)-                 "Options.fullDesc" Options.fullDesc :: forall a. Options.InfoMod a-                 "Options.flag" Options.flag :: forall a. a -> a -> Options.Mod Options.FlagFields a -> Parser a-                 "Options.flag'" Options.flag' :: forall a. a -> Options.Mod Options.FlagFields a -> Parser a-                 "Option.long" option_long :: forall a. Text -> Options.Mod Options.OptionFields a-                 "Option.help" options_help :: forall a. Text -> Options.Mod Options.OptionFields a-                 "Flag.help" options_help :: forall a. Text -> Options.Mod Options.FlagFields a-                 "Flag.long" flag_long :: forall a. Text -> Options.Mod Options.FlagFields a-                 "Option.value" option_value :: forall a. a -> Options.Mod Options.OptionFields a-                 "Argument.value" argument_value :: forall a. a -> Options.Mod Options.ArgumentFields a-                 "Argument.metavar" argument_metavar :: forall a. Text -> Options.Mod Options.ArgumentFields a-                 "Argument.help" options_help :: forall a. Text -> Options.Mod Options.ArgumentFields a-               |]-     )------------------------------------------------------------------------------------- Internal-use only, used by the desugarer--argument_metavar :: forall a. Text -> Options.Mod Options.ArgumentFields a-argument_metavar = Options.metavar . Text.unpack--option_value :: forall a. a -> Options.Mod Options.OptionFields a-option_value = Options.value--argument_value :: forall a. a -> Options.Mod Options.ArgumentFields a-argument_value = Options.value--options_help :: forall f a. Text -> Options.Mod f a-options_help = Options.help . Text.unpack--option_long :: forall a. Text -> Options.Mod Options.OptionFields a-option_long = Options.long . Text.unpack--flag_long :: forall a. Text -> Options.Mod Options.FlagFields a-flag_long = Options.long . Text.unpack--cons' :: HSE.SrcSpanInfo -> UTerm ()-cons' = unsafeGetForall "List.cons"--nil' :: HSE.SrcSpanInfo -> UTerm ()-nil' = unsafeGetForall "List.nil"--bool' :: HSE.SrcSpanInfo -> UTerm ()-bool' = unsafeGetForall "Bool.bool"--tuple' :: Int -> HSE.SrcSpanInfo -> UTerm ()-tuple' 0 = unsafeGetForall "Tuple.()"-tuple' 2 = unsafeGetForall "Tuple.(,)"-tuple' 3 = unsafeGetForall "Tuple.(,,)"-tuple' 4 = unsafeGetForall "Tuple.(,,,)"-tuple' _ = error "Bad compile-time lookup for tuple'."--unsafeGetForall :: String -> HSE.SrcSpanInfo -> UTerm ()-unsafeGetForall key l = Maybe.fromMaybe (error $ "Bad compile-time lookup for " ++ key) $ do-  (forall', vars, irep, _) <- Map.lookup key polyLits-  pure (UForall l () [] forall' vars irep [])------------------------------------------------------------------------------------- Hidden terms and types, implementation-detail, used by Hell--hellModule :: l -> HSE.ModuleName l-hellModule l = HSE.ModuleName l "hell:Hell"--hellQName :: l -> String -> HSE.QName l-hellQName l string = HSE.Qual l (hellModule l) (HSE.Ident l string)--hellTyCon :: l -> String -> HSE.Type l-hellTyCon l string = HSE.TyCon l $ hellQName l string--hellCon :: l -> String -> HSE.Exp l-hellCon l string = HSE.Con l $ hellQName l string--hellTaggedTyCon :: l -> HSE.Type l-hellTaggedTyCon l = hellTyCon l "Tagged"--hellRecordTyCon :: l -> HSE.Type l-hellRecordTyCon l = hellTyCon l "Record"--hellVariantTyCon :: l -> HSE.Type l-hellVariantTyCon l = hellTyCon l "Variant"--hellNilTyCon :: l -> HSE.Type l-hellNilTyCon l = hellTyCon l "NilL"--hellConsTyCon :: l -> HSE.Type l-hellConsTyCon l = hellTyCon l "ConsL"--hellTaggedCon :: l -> HSE.Exp l-hellTaggedCon l = hellCon l "Tagged"------------------------------------------------------------------------------------- Accessor for ExitCode--exit_exitCode :: a -> (Int -> a) -> ExitCode -> a-exit_exitCode ok fail' = \case-  ExitSuccess -> ok-  ExitFailure i -> fail' i------------------------------------------------------------------------------------- UTF-8 specific operations without all the environment gubbins------ Much better than what Data.Text.IO provides--bytestring_readFile :: Text -> IO ByteString-bytestring_readFile = ByteString.readFile . Text.unpack--bytestring_writeFile :: Text -> ByteString -> IO ()-bytestring_writeFile = ByteString.writeFile . Text.unpack--t_setStdin :: Text -> ProcessConfig () () () -> ProcessConfig () () ()-t_setStdin text = setStdin (byteStringInput (L.fromStrict (Text.encodeUtf8 text)))--t_readProcess :: ProcessConfig () () () -> IO (ExitCode, Text, Text)-t_readProcess c = do-  (code, out, err) <- b_readProcess c-  pure (code, Text.decodeUtf8 out, Text.decodeUtf8 err)--t_readProcess_ :: ProcessConfig () () () -> IO (Text, Text)-t_readProcess_ c = do-  (out, err) <- b_readProcess_ c-  pure (Text.decodeUtf8 out, Text.decodeUtf8 err)--t_readProcessStdout_ :: ProcessConfig () () () -> IO Text-t_readProcessStdout_ c = do-  out <- b_readProcessStdout_ c-  pure (Text.decodeUtf8 out)--t_putStrLn :: Text -> IO ()-t_putStrLn = ByteString.hPutBuilder IO.stdout . (<> "\n") . ByteString.byteString . Text.encodeUtf8--t_hPutStr :: IO.Handle -> Text -> IO ()-t_hPutStr h = ByteString.hPutBuilder h . ByteString.byteString . Text.encodeUtf8--t_putStr :: Text -> IO ()-t_putStr = t_hPutStr IO.stdout--t_getLine :: IO Text-t_getLine = fmap Text.decodeUtf8 ByteString.getLine--t_writeFile :: Text -> Text -> IO ()-t_writeFile fp t = ByteString.writeFile (Text.unpack fp) (Text.encodeUtf8 t)--t_appendFile :: Text -> Text -> IO ()-t_appendFile fp t = ByteString.appendFile (Text.unpack fp) (Text.encodeUtf8 t)--t_readFile :: Text -> IO Text-t_readFile fp = fmap Text.decodeUtf8 (ByteString.readFile (Text.unpack fp))------------------------------------------------------------------------------------- JSON operations---- Accessor for JSON.-json_value ::-  forall a.-  a -> -- Null-  (Bool -> a) -> -- Bool-  (Text -> a) -> -- String-  (Double -> a) -> -- Number-  (Vector Value -> a) -> -- Array-  (Map Text Value -> a) -> -- Object-  Value ->-  a-json_value null' bool string number array object =-  \case-    Json.Null -> null'-    Json.Bool s -> bool s-    Json.String s -> string s-    Json.Number s -> number (realToFrac s)-    Json.Array s -> array s-    Json.Object s -> object $ KeyMap.toMapText $ s------------------------------------------------------------------------------------- ByteString operations--b_readProcess :: ProcessConfig () () () -> IO (ExitCode, ByteString, ByteString)-b_readProcess c = do-  (code, out, err) <- readProcess c-  pure (code, L.toStrict out, L.toStrict err)--b_readProcess_ :: ProcessConfig () () () -> IO (ByteString, ByteString)-b_readProcess_ c = do-  (out, err) <- readProcess_ c-  pure (L.toStrict out, L.toStrict err)--b_readProcessStdout_ :: ProcessConfig () () () -> IO ByteString-b_readProcessStdout_ c = do-  out <- readProcessStdout_ c-  pure (L.toStrict out)------------------------------------------------------------------------------------- Temp file operations--temp_withSystemTempFile :: forall a. Text -> (Text -> IO.Handle -> IO a) -> IO a-temp_withSystemTempFile template action = Temp.withSystemTempFile (Text.unpack template) $ \fp h -> action (Text.pack fp) h--temp_withSystemTempDirectory :: forall a. Text -> (Text -> IO a) -> IO a-temp_withSystemTempDirectory template action = Temp.withSystemTempDirectory (Text.unpack template) $ \fp -> action (Text.pack fp)------------------------------------------------------------------------------------- Process operations--process_setWorkingDir :: forall a b c. Text -> ProcessConfig a b c -> ProcessConfig a b c-process_setWorkingDir filepath = Process.setWorkingDir (Text.unpack filepath)------------------------------------------------------------------------------------- Inference type representation--data IRep v-  = IVar v-  | IApp (IRep v) (IRep v)-  | IFun (IRep v) (IRep v)-  | ICon SomeTypeRep-  deriving (Functor, Traversable, Foldable, Eq, Ord, Show)--data ZonkError-  = ZonkKindError-  | AmbiguousMetavar IMetaVar-  deriving (Show)---- | A complete implementation of conversion from the inferer's type--- rep to some star type, ready for the type checker.-toSomeTypeRep :: IRep Void -> Either ZonkError SomeTypeRep-toSomeTypeRep t = do-  go t-  where-    go :: IRep Void -> Either ZonkError SomeTypeRep-    go = \case-      IVar v -> pure (absurd v)-      ICon someTypeRep -> pure someTypeRep-      IFun a b -> do-        a' <- go a-        b' <- go b-        case (a', b') of-          (StarTypeRep aRep, StarTypeRep bRep) ->-            pure $ StarTypeRep (Type.Fun aRep bRep)-          _ -> Left ZonkKindError-      IApp f a -> do-        f' <- go f-        a' <- go a-        case applyTypes f' a' of-          Just someTypeRep -> pure someTypeRep-          _ -> Left ZonkKindError---- | Convert from a type-indexed type to an untyped type.-fromSomeStarType :: forall void. SomeStarType -> IRep void-fromSomeStarType (SomeStarType r) = fromSomeType (SomeTypeRep r)--fromSomeType :: forall void. SomeTypeRep -> IRep void-fromSomeType (SomeTypeRep r) = go r-  where-    go :: forall a. TypeRep a -> IRep void-    go = \case-      Type.Fun a b -> IFun (go a) (go b)-      Type.App a b -> IApp (go a) (go b)-      rep@Type.Con {} -> ICon (SomeTypeRep rep)------------------------------------------------------------------------------------- Inference elaboration phase--data IMetaVar = IMetaVar0 {index :: Int, srcSpanInfo :: HSE.SrcSpanInfo}-  deriving (Ord, Eq, Show)--data Elaborate = Elaborate-  { counter :: Int,-    equalities :: Set (Equality (IRep IMetaVar))-  }--data Equality a = Equality HSE.SrcSpanInfo a a-  deriving (Show, Functor)---- Equality/ordering that is symmetric.-instance (Ord a) => Eq (Equality a) where-  Equality _ a b == Equality _ c d = Set.fromList [a, b] == Set.fromList [c, d]--instance (Ord a) => Ord (Equality a) where-  Equality _ a b `compare` Equality _ c d = Set.fromList [a, b] `compare` Set.fromList [c, d]--data ElaborateError = UnsupportedTupleSize | BadInstantiationBug | VariableNotInScope String-  deriving (Show)---- | Elaboration phase.------ Note: The input term contains no metavars. There are just some--- UForalls, which have poly types, and those are instantiated into--- metavars.------ Output type /does/ contain meta vars.-elaborate :: UTerm () -> Either ElaborateError (UTerm (IRep IMetaVar), Set (Equality (IRep IMetaVar)))-elaborate = fmap getEqualities . flip runStateT empty . flip runReaderT mempty . go-  where-    empty = Elaborate {counter = 0, equalities = mempty}-    getEqualities (term, Elaborate {equalities}) = (term, equalities)-    go :: UTerm () -> ReaderT (Map String (IRep IMetaVar)) (StateT Elaborate (Either ElaborateError)) (UTerm (IRep IMetaVar))-    go = \case-      UVar l () string -> do-        env <- ask-        ty <- case Map.lookup string env of-          Just typ -> pure typ-          Nothing -> lift $ lift $ Left $ VariableNotInScope string-        pure $ UVar l ty string-      UApp l () f x -> do-        f' <- go f-        x' <- go x-        b <- fmap IVar $ freshIMetaVar l-        equal l (typeOf f') (IFun (typeOf x') b)-        pure $ UApp l b f' x'-      ULam l () binding mstarType body -> do-        a <- case mstarType of-          Just ty -> pure $ fromSomeStarType ty-          Nothing -> fmap IVar $ freshIMetaVar l-        vars <- lift $ bindingVars l a binding-        body' <- local (Map.union vars) $ go body-        let ty = IFun a (typeOf body')-        pure $ ULam l ty binding mstarType body'-      UForall l () types forall' uniqs polyRep _ -> do-        -- Generate variables for each unique.-        vars <- for uniqs \uniq -> do-          v <- freshIMetaVar l-          pure (uniq, v)-        -- Fill in the polyRep with the metavars.-        monoType <- for polyRep \uniq ->-          case List.lookup uniq vars of-            Nothing -> lift $ lift $ Left $ BadInstantiationBug-            Just var -> pure var-        -- Order of types is position-dependent, apply the ones we have.-        for_ (zip vars types) \((_uniq, var), someTypeRep) ->-          equal l (fromSomeType someTypeRep) (IVar var)-        -- Done!-        pure $ UForall l monoType types forall' uniqs polyRep (map (IVar . snd) vars)--bindingVars :: HSE.SrcSpanInfo -> IRep IMetaVar -> Binding -> StateT Elaborate (Either ElaborateError) (Map String (IRep IMetaVar))-bindingVars _ irep (Singleton name) = pure $ Map.singleton name irep-bindingVars l tupleVar (Tuple names) = do-  varsTypes <- for names \name -> fmap (name,) (fmap IVar (freshIMetaVar l))-  -- it's a left-fold:-  -- IApp (IApp (ICon (,)) x) y-  cons <- makeCons-  equal l tupleVar $ foldl IApp (ICon cons) (map snd varsTypes)-  pure $ Map.fromList varsTypes-  where-    makeCons = case length names of-      2 -> pure $ SomeTypeRep (typeRep @(,))-      3 -> pure $ SomeTypeRep (typeRep @(,,))-      4 -> pure $ SomeTypeRep (typeRep @(,,,))-      _ -> lift $ Left $ UnsupportedTupleSize--equal :: (MonadState Elaborate m) => HSE.SrcSpanInfo -> IRep IMetaVar -> IRep IMetaVar -> m ()-equal l x y = modify \elaborate' -> elaborate' {equalities = equalities elaborate' <> Set.singleton (Equality l x y)}--freshIMetaVar :: (MonadState Elaborate m) => HSE.SrcSpanInfo -> m IMetaVar-freshIMetaVar srcSpanInfo = do-  Elaborate {counter} <- get-  modify \elaborate' -> elaborate' {counter = counter + 1}-  pure $ IMetaVar0 counter srcSpanInfo------------------------------------------------------------------------------------- Unification--data UnifyError-  = OccursCheck-  | TypeMismatch HSE.SrcSpanInfo (IRep IMetaVar) (IRep IMetaVar)-  deriving (Show)---- | Unification of equality constraints, a ~ b, to substitutions.-unify :: Set (Equality (IRep IMetaVar)) -> Either UnifyError (Map IMetaVar (IRep IMetaVar))-unify = foldM update mempty-  where-    update existing equality =-      fmap-        (`extends` existing)-        (examine (fmap (substitute existing) equality))-    examine (Equality l a b)-      | a == b = pure mempty-      | IVar ivar <- a = bindMetaVar ivar b-      | IVar ivar <- b = bindMetaVar ivar a-      | IFun a1 b1 <- a,-        IFun a2 b2 <- b =-          unify (Set.fromList [Equality l a1 a2, Equality l b1 b2])-      | IApp a1 b1 <- a,-        IApp a2 b2 <- b =-          unify (Set.fromList [Equality l a1 a2, Equality l b1 b2])-      | ICon x <- a,-        ICon y <- b =-          if x == y-            then pure mempty-            else Left $ TypeMismatch l a b-      | otherwise = Left $ TypeMismatch l a b---- | Apply new substitutions to the old ones, and expand the set to old+new.-extends :: Map IMetaVar (IRep IMetaVar) -> Map IMetaVar (IRep IMetaVar) -> Map IMetaVar (IRep IMetaVar)-extends new old = fmap (substitute new) old <> new---- | Apply any substitutions to the type, where there are metavars.-substitute :: Map IMetaVar (IRep IMetaVar) -> IRep IMetaVar -> IRep IMetaVar-substitute subs = go-  where-    go = \case-      IVar v -> case Map.lookup v subs of-        Nothing -> IVar v-        Just ty -> ty-      ICon c -> ICon c-      IFun a b -> IFun (go a) (go b)-      IApp a b -> IApp (go a) (go b)---- | Do an occurrs check, if all good, return a binding.-bindMetaVar ::-  IMetaVar ->-  IRep IMetaVar ->-  Either UnifyError (Map IMetaVar (IRep IMetaVar))-bindMetaVar var typ-  | occurs var typ = Left OccursCheck-  | otherwise = pure $ Map.singleton var typ---- | Occurs check.-occurs :: IMetaVar -> IRep IMetaVar -> Bool-occurs ivar = any (== ivar)---- | Remove any metavars from the type.------ <https://stackoverflow.com/questions/31889048/what-does-the-ghc-source-mean-by-zonk>-zonk :: IRep IMetaVar -> Either ZonkError (IRep Void)-zonk = \case-  IVar var -> Left $ AmbiguousMetavar var-  ICon c -> pure $ ICon c-  IFun a b -> IFun <$> zonk a <*> zonk b-  IApp a b -> IApp <$> zonk a <*> zonk b------------------------------------------------------------------------------------- Parse with #!/shebangs--data File = File {-  terms :: [(String, HSE.Exp HSE.SrcSpanInfo)],-  types :: [(String, HSE.Type HSE.SrcSpanInfo)]-  }---- Parse a file into a list of decls, but strip shebangs.-parseFile :: String -> IO (Either String File)-parseFile filePath = do-  string <- ByteString.readFile filePath-  pure $ case HSE.parseModuleWithMode HSE.defaultParseMode {HSE.parseFilename = filePath, HSE.extensions = HSE.extensions HSE.defaultParseMode ++ [HSE.EnableExtension HSE.PatternSignatures, HSE.EnableExtension HSE.DataKinds, HSE.EnableExtension HSE.BlockArguments, HSE.EnableExtension HSE.TypeApplications]} (Text.unpack (dropShebang (Text.decodeUtf8 string))) >>= parseModule of-    HSE.ParseFailed l e -> Left $ "Parse error: " <> HSE.prettyPrint l <> ": " <> e-    HSE.ParseOk file -> Right file---- This should be quite efficient because it's essentially a pointer--- increase. It leaves the \n so that line numbers are intact.-dropShebang :: Text -> Text-dropShebang t = Maybe.fromMaybe t do-  rest <- Text.stripPrefix "#!" t-  pure $ Text.dropWhile (/= '\n') rest------------------------------------------------------------------------------------- Spec--_spec :: Spec-_spec = do-  freeVariablesSpec-  anyCyclesSpec-  desugarTypeSpec------------------------------------------------------------------------------------- Records--data Tagged (s :: Symbol) a = Tagged a--data List = NilL | ConsL Symbol Type List--data Record (xs :: List) where-  NilR :: Record 'NilL-  ConsR :: forall k a xs. a -> Record xs -> Record (ConsL k a xs)---- | Build up a type-safe getter.-makeAccessor ::-  forall k r0 a t.-  TypeRep (k :: Symbol) ->-  TypeRep (r0 :: List) ->-  TypeRep a ->-  TypeRep t ->-  Maybe (Tagged t (Record (r0 :: List)) -> a)-makeAccessor k r0 a _ = do-  accessor <- go r0-  pure \(Tagged r) -> accessor r-  where-    go :: TypeRep (r :: List) -> Maybe (Record (r :: List) -> a)-    go r =-      case Type.eqTypeRep r (Type.TypeRep @NilL) of-        Just {} -> Nothing-        Nothing ->-          case r of-            Type.App (Type.App (Type.App _ sym) typ) r'-              | Just Type.HRefl <- Type.eqTypeRep (typeRepKind typ) (typeRep @Type),-                Just Type.HRefl <- Type.eqTypeRep (typeRepKind sym) (typeRep @Symbol),-                Just Type.HRefl <- Type.eqTypeRep (typeRepKind r') (typeRep @List) ->-                  case (Type.eqTypeRep k sym, Type.eqTypeRep a typ) of-                    (Just Type.HRefl, Just Type.HRefl) ->-                      pure \(ConsR v _xs) -> v-                    _ -> do-                      accessor <- go r'-                      pure \case-                        ConsR _a xs -> accessor xs-            _ -> Nothing---- | Build up a type-safe setter.-makeSetter ::-  forall k r0 a t.-  TypeRep (k :: Symbol) ->-  TypeRep (r0 :: List) ->-  TypeRep a ->-  TypeRep t ->-  Maybe (a -> Tagged t (Record (r0 :: List)) -> Tagged t (Record (r0 :: List)))-makeSetter k r0 a _ = do-  setter <- go r0-  pure \a' (Tagged r) -> Tagged (setter a' r)-  where-    go :: TypeRep (r :: List) -> Maybe (a -> Record (r :: List) -> Record (r :: List))-    go r =-      case Type.eqTypeRep r (Type.TypeRep @NilL) of-        Just {} -> Nothing-        Nothing ->-          case r of-            Type.App (Type.App (Type.App _ sym) typ) r'-              | Just Type.HRefl <- Type.eqTypeRep (typeRepKind typ) (typeRep @Type),-                Just Type.HRefl <- Type.eqTypeRep (typeRepKind sym) (typeRep @Symbol),-                Just Type.HRefl <- Type.eqTypeRep (typeRepKind r') (typeRep @List) ->-                  case (Type.eqTypeRep k sym, Type.eqTypeRep a typ) of-                    (Just Type.HRefl, Just Type.HRefl) ->-                      pure \a' (ConsR _a xs) -> ConsR a' xs-                    _ -> do-                      setter <- go r'-                      pure \a' (ConsR a0 xs) -> ConsR a0 (setter a' xs)-            _ -> Nothing---- | Simply re-uses makeAccessor and makeSetter.-makeModify ::-  forall k r0 a t.-  TypeRep (k :: Symbol) ->-  TypeRep (r0 :: List) ->-  TypeRep a ->-  TypeRep t ->-  Maybe ((a -> a) -> Tagged t (Record (r0 :: List)) -> Tagged t (Record (r0 :: List)))-makeModify k0 r0 a0 t0 = do-  getter <- makeAccessor k0 r0 a0 t0-  setter <- makeSetter k0 r0 a0 t0-  pure \f record -> setter (f (getter record)) record------------------------------------------------------------------------------------- Variants---- | A variant; one of the given choices.-data Variant (xs :: List) where-  LeftV :: forall k a xs. a -> Variant (ConsL k a xs)-  RightV :: forall k a xs k'' a''. Variant (ConsL k'' a'' xs) -> Variant (ConsL k a (ConsL k'' a'' xs))---- | Accessor of a given variant. A record whose fields all correspond--- to the constructors of a sum type, and whose types are all `a ->--- r` instead of `a`.-data Accessor (xs :: List) r where-  NilA :: Accessor 'NilL r-  ConsA :: forall k a r xs. (a -> r) -> Accessor xs r -> Accessor (ConsL k a xs) r---- | Run a total case-analysis against a variant, given an accessor--- record.-runAccessor :: Tagged s (Variant xs) -> Accessor xs r -> r-runAccessor (Tagged (LeftV a)) (ConsA f _) = f a-runAccessor (Tagged (RightV xs)) (ConsA _ ys) = runAccessor (Tagged xs) ys------------------------------------------------------------------------------------- Pretty printing---- | Convenience.-prettyString :: (Pretty a) => a -> String-prettyString =-  Text.unpack . Text.decodeUtf8 . L.toStrict . ByteString.toLazyByteString . pretty--class Pretty a where-  pretty :: a -> ByteString.Builder--instance Pretty String where-  pretty r =-    ByteString.byteString (Text.encodeUtf8 $ Text.pack r)--instance Pretty SomeTypeRep where-  pretty r =-    ByteString.byteString (Text.encodeUtf8 $ Text.pack $ show r)--instance Pretty (TypeRep t) where-  pretty r =-    ByteString.byteString (Text.encodeUtf8 $ Text.pack $ show r)--instance Pretty IMetaVar where-  pretty (IMetaVar0 i _) =-    "t"-      <> ByteString.byteString (Text.encodeUtf8 $ Text.pack $ show i)--instance (Pretty a) => Pretty (IRep a) where-  pretty = \case-    IVar a -> pretty a-    ICon a -> pretty a-    IApp f x -> "(" <> pretty f <> " " <> pretty x <> ")"-    IFun a b -> "(" <> pretty a <> " -> " <> pretty b <> ")"--instance Pretty ZonkError where-  pretty = \case-    ZonkKindError -> "Kind error."-    AmbiguousMetavar imetavar ->-      "Ambiguous meta variable: "-        <> pretty imetavar-        <> "\n"-        <> "arising from "-        <> pretty imetavar.srcSpanInfo--instance Pretty ElaborateError where-  pretty = \case-    UnsupportedTupleSize -> "That tuple size is not supported."-    BadInstantiationBug -> "BUG: BadInstantiationBug. Please report."-    VariableNotInScope s -> "Variable not in scope: " <> pretty s--instance Pretty UnifyError where-  pretty = \case-    OccursCheck -> "Occurs check failed: Infinite type."-    TypeMismatch l a b ->-      mconcat $-        List.intersperse-          "\n\n"-          [ "Couldn't match type",-            "  " <> pretty a,-            "against type",-            "  " <> pretty b,-            "arising from " <> pretty l-          ]--instance Pretty HSE.SrcSpanInfo where-  pretty l =-    mconcat-      [ pretty (HSE.fileName l),-        ":",-        pretty $ show $ HSE.startLine l,-        ":",-        pretty $ show $ HSE.startColumn l-      ]--instance Pretty TypeCheckError where-  pretty = \case-    NotInScope s -> "Not in scope: " <> pretty s-    TupleTypeMismatch -> "Tuple type mismatch!"-    TypeCheckMismatch -> "Type check mismatch."-    TupleTypeTooBig -> "Tuple type is too big."-    TypeOfApplicandIsNotFunction -> "Type of application is not a function."-    LambdaIsNotAFunBug -> "BUG: LambdaIsNotAFunBug. Please report."-    InferredCheckedDisagreeBug -> "BUG: Inferred type disagrees with checked type. Please report."-    LambdaMustBeStarBug -> "BUG: Lambda should be of kind *, but isn't. Please report."--instance Pretty DesugarError where-  pretty = \case-    InvalidConstructor c -> "Invalid constructor: " <> pretty c-    InvalidVariable c -> "Invalid variable: " <> pretty c-    UnknownType t -> "Unknown type: " <> pretty t-    UnsupportedSyntax s -> "Unsupported syntax: " <> pretty s-    BadParameterSyntax s -> "Bad parameter syntax: " <> pretty s-    KindError -> "Kind error."-    BadDoNotation -> "Bad do notation."-    TupleTooBig -> "That tuple size is not supported."-    UnsupportedLiteral -> "That literal type is not supported."--instance Pretty InferError where-  pretty = \case-    UnifyError e -> "Unification error: " <> pretty e-    ZonkError e -> "Zonk error: " <> pretty e-    ElabError e -> "Elaboration error: " <> pretty e------------------------------------------------------------------------------------- Generate docs--_generateApiDocs :: IO ()-_generateApiDocs = do-  css <- Text.readFile "docs/style.css"-  Lucid.renderToFile "docs/api/index.html" do-    doctypehtml_ do-      style_ css-      head_ do-        title_ "Hell's API"-      body_ do-        h1_ "Hell's API"-        h2_ $ do "Version: "; toHtml hellVersion-        p_ $ a_ [href_ "../"] $ "Back to homepage"-        h2_ "Types"-        let excludeHidden = filter (not . List.isPrefixOf "hell:Hell." . fst)-        ul_ do-          for_ (excludeHidden $ Map.toList supportedTypeConstructors) typeConsToHtml-        h2_ "Terms"-        let groups =-              excludeHidden $-              Map.toList $ fmap (Left . snd) $-               supportedLits-        let groups' = excludeHidden  $-              Map.toList $ fmap (\(_, _, _, ty) -> Right ty) polyLits-        for_ (List.groupBy (Function.on (==) (takeWhile (/= '.') . fst)) $ List.sortOn fst $ groups <> groups') \group -> do-          h3_ $ for_ (take 1 group) \(x, _) -> toHtml $ takeWhile (/= '.') x-          ul_ do-            for_ group \(x, a) -> case a of-              Left e -> litToHtml (x, e)-              Right e -> polyToHtml (x, e)--typeConsToHtml :: (String, SomeTypeRep) -> Html ()-typeConsToHtml (name, SomeTypeRep rep) =-  li_ do-    code_ do-      em_ "data "-      strong_ $ toHtml name-      em_ " :: "-      toHtml $ prettyString $ typeRepKind rep--litToHtml :: (String, SomeTypeRep) -> Html ()-litToHtml (name, SomeTypeRep rep) =-  li_ do-    code_ do-      strong_ $ toHtml name-      em_ " :: "-      toHtml $ prettyString $ rep--polyToHtml :: (String, TH.Type) -> Html ()-polyToHtml (name, ty) =-  li_ do-    code_ do-      strong_ $ toHtml name-      em_ " :: "-      toHtml $ TH.pprint $ cleanUpTHType ty--cleanUpTHType :: TH.Type -> TH.Type-cleanUpTHType = SYB.everywhere unqualify-  where-    unqualify :: forall a. (Type.Typeable a) => a -> a-    unqualify a =-      case Type.eqTypeRep (Type.typeRep @a) (Type.typeRep @TH.Name) of-        Nothing -> a-        Just Type.HRefl ->-          TH.mkName $ TH.nameBase a+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE ExistentialQuantification, DuplicateRecordFields, NoFieldSelectors #-}+{-# LANGUAGE ExtendedDefaultRules #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedRecordDot #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}+--+-- Welcome to Hell+--+-- Haskell as a scripting language!+--+-- Special thanks to Stephanie Weirich, whose type-safe typechecker+-- this is built upon, and for the Type.Reflection module, which has+-- made some of this more ergonomic.+{-# OPTIONS_GHC -Wno-unused-foralls #-}++module Main (main, specMain) where++#if __GLASGOW_HASKELL__ >= 906+import Control.Monad+#endif++-- All modules tend to be imported qualified by their last component,+-- e.g. 'Data.Graph' becomes 'Graph', and are then exposed to the Hell+-- guest language as such.++import Control.Applicative (Alternative (..), optional)+import qualified Control.Concurrent as Concurrent+import Control.Exception (evaluate)+import Control.Monad.Reader+import Control.Monad.State.Strict+import Criterion.Measurement+import Data.Aeson (Value)+import qualified Data.Aeson as Json+import qualified Data.Aeson.KeyMap as KeyMap+import Data.Bifunctor+import qualified Data.Bool as Bool+import Data.ByteString (ByteString)+import qualified Data.ByteString as ByteString+import qualified Data.ByteString.Builder as ByteString hiding (writeFile)+import qualified Data.ByteString.Char8 as S8+import qualified Data.ByteString.Lazy as L+import Data.Constraint+import Data.Containers.ListUtils+import Data.Dynamic+import qualified Data.Either as Either+import qualified Data.Eq as Eq+import Data.Foldable+import qualified Data.Function as Function+import qualified Data.Generics as SYB+import qualified Data.Graph as Graph+import qualified Data.List as List+import qualified Data.Map as Map+import Data.Map.Strict (Map)+import qualified Data.Maybe as Maybe+import qualified Data.Ord as Ord+import Data.Set (Set)+import qualified Data.Set as Set+import Data.Text (Text)+import qualified Data.Text as Text+import qualified Data.Text.Encoding as Text+import qualified Data.Text.IO as Text+import Data.These (These)+import qualified Data.These as These+import Data.Time (Day, TimeOfDay, UTCTime)+import qualified Data.Time as Time+import qualified Data.Time.Format.ISO8601 as Time+import Data.Traversable+import Data.Tree (Tree)+import qualified Data.Tree as Tree+import Data.Vector (Vector)+import qualified Data.Vector as Vector+import Data.Void+import GHC.TypeLits+import GHC.Types (Type)+import qualified Language.Haskell.Exts as HSE+import Language.Haskell.TH (Q)+import qualified Language.Haskell.TH as TH+import Language.Haskell.TH.Instances ()+import qualified Language.Haskell.TH.Syntax as TH+import Lucid hiding (Term, for_, term)+import Numeric+import Options.Applicative (Parser)+import qualified Options.Applicative as Options+import qualified System.Directory as Dir+import System.Environment+import qualified System.Exit as Exit+import qualified System.IO as IO+import qualified System.IO.Temp as Temp+import System.Process.Typed as Process+import qualified System.Timeout as Timeout+import Test.Hspec+import qualified Text.Read as Read+import qualified Text.Show as Show+import Type.Reflection (SomeTypeRep (..), TypeRep, typeRep, typeRepKind, pattern TypeRep)+import qualified Type.Reflection as Type+import qualified UnliftIO.Async as Async++------------------------------------------------------------------------------+-- Main entry point++-- | Commands available.+data Command+  = Run FilePath+  | Check FilePath StatsEnabled+  | Version++data StatsEnabled = NoStats | PrintStats Int++-- | Main entry point.+main :: IO ()+main = do+  initializeTime+  args <- getArgs+  case args of+    (x : ys)+      | not (List.isPrefixOf "-" x) -> withArgs ys $ dispatch (Run x)+    _ -> dispatch =<< Options.execParser opts+  where+    opts =+      Options.info+        (commandParser Options.<**> Options.helper)+        ( Options.fullDesc+            <> Options.progDesc "Runs and typechecks Hell scripts"+            <> Options.header "hell - A Haskell-driven scripting language"+        )++-- | Command options.+commandParser :: Options.Parser Command+commandParser =+  Options.asum+    [ Run <$> Options.strArgument (Options.metavar "FILE" <> Options.help "Run the given .hell file"),+      Check+        <$> Options.strOption (Options.long "check" <> Options.metavar "FILE" <> Options.help "Typecheck the given .hell file")+        <*> Options.flag NoStats (PrintStats 0) (Options.long "compiler-stats" <> Options.internal),+      Version <$ Options.flag () () (Options.long "version" <> Options.help "Print the version")+    ]++-- | Version of Hell.+hellVersion :: Text+hellVersion = "2025-11-11"++-- | Dispatch on the command.+dispatch :: Command -> IO ()+dispatch Version = Text.putStrLn hellVersion+dispatch (Run filePath) = do+  action <- compileFile NoStats filePath+  eval () action+dispatch (Check filePath stats) = do+  compileFile stats filePath >>= void . evaluate++--------------------------------------------------------------------------------+-- Compiler++-- | Parses the file with HSE, desugars it, infers it, checks it,+-- returns it. Or throws an error.+compileFile :: StatsEnabled -> FilePath -> IO (Term () (IO ()))+compileFile stats filePath = do+  t0 <- getTime+  !result <- parseFile (nestStat stats) filePath+  t1 <- getTime+  emitStat stats "parse" (t1 - t0)+  case result of+    Left e -> error $ e+    Right File {terms, types}+      | anyCycles terms -> error "Cyclic bindings are not supported!"+      | anyCycles types -> error "Cyclic types are not supported!"+      | otherwise -> do+          t2 <- getTime+          emitStat stats "cycle_detect" (t2 - t1)+          case desugarAll types terms of+            Left err -> error $ prettyString err+            Right !dterms -> do+              t3 <- getTime+              emitStat stats "desugar" (t3 - t2)+              case lookup "main" dterms of+                Nothing -> error "No main declaration!"+                Just main' -> do+                  inferred <- inferExp (nestStat stats) main'+                  case inferred of+                    Left err -> error $ prettyString err+                    Right uterm -> do+                      t4 <- getTime+                      emitStat stats "infer" (t4 - t3)+                      case check uterm Nil of+                        Left err -> error $ prettyString err+                        Right (Typed t ex) -> do+                          t5 <- getTime+                          emitStat stats "check" (t5 - t4)+                          case Type.eqTypeRep (typeRepKind t) (typeRep @Type) of+                            Nothing -> error $ "Kind error, that's nowhere near an IO ()!"+                            Just Type.HRefl ->+                              case Type.eqTypeRep t (typeRep @(IO ())) of+                                Just Type.HRefl ->+                                  pure ex+                                Nothing -> error $ "Type isn't IO (), but: " ++ show t++emitStat :: StatsEnabled -> Text -> Double -> IO ()+emitStat NoStats _ _ = pure ()+emitStat (PrintStats n0) label s =+  t_putStrLn $ Text.replicate (n0 * 2) " " <> "stat: " <> label <> " = " <> Text.pack (secs s)++nestStat :: StatsEnabled -> StatsEnabled+nestStat NoStats = NoStats+nestStat (PrintStats n) = PrintStats (n + 1)++--------------------------------------------------------------------------------+-- Get declarations from the module++parseModule :: HSE.Module HSE.SrcSpanInfo -> HSE.ParseResult File+parseModule (HSE.Module _ Nothing [] [] decls) = do+  termsAndTypes <- traverse parseDecl decls+  let terms = concatMap fst termsAndTypes+      types = concatMap snd termsAndTypes+  let names = map fst terms+      tyNames = map fst types+  if Set.size (Set.fromList names) == length names+    && Set.size (Set.fromList tyNames) == length tyNames+    then pure File {terms, types}+    else fail "Duplicate names!"+  where+    parseDecl (HSE.PatBind _ (HSE.PVar _ (HSE.Ident _ string)) (HSE.UnGuardedRhs _ exp') Nothing) =+      pure ([(string, exp')], types)+      where+        types = []+    parseDecl+      ( HSE.PatBind+          _+          ( HSE.PatTypeSig+              l+              (HSE.PVar _ (HSE.Ident _ string))+              typ+            )+          (HSE.UnGuardedRhs _ exp')+          Nothing+        ) =+        pure ([(string, HSE.ExpTypeSig l exp' typ)], types)+        where+          types = []+    parseDecl (HSE.DataDecl _ HSE.DataType {} Nothing (HSE.DHead _ name) [qualConDecl] []) =+      do+        (termName, termExpr, typeName, typ) <- parseDataDecl name qualConDecl+        pure ([(termName, termExpr)], [(typeName, typ)])+    parseDecl (HSE.DataDecl _ HSE.DataType {} Nothing (HSE.DHead _ name) qualConDecls []) =+      do+        (terms, tyname, typ) <- parseSumDecl name qualConDecls+        pure (terms, [(tyname, typ)])+    parseDecl d = fail $ "Can't parse that! " ++ show d+parseModule _ = fail "Module headers aren't supported."++-- data Value = Text Text | Number Int+-- \ x ->+--   hell:Hell.Tagged @"Main.Value"+--     @(Variant (ConsL "Number" Int (ConsL "Text" Text NilL)))+--     (Variant.left @"Number" x)+-- \ x ->+--   hell:Hell.Tagged @"Main.Value"+--     @(Variant (ConsL "Number" Int (ConsL "Text" Text NilL)))+--     (Variant.right (Variant.left @"Text" x))+parseSumDecl ::+  (l ~ HSE.SrcSpanInfo) =>+  HSE.Name l ->+  [HSE.QualConDecl l] ->+  -- | ^^^^ type name and type+  HSE.ParseResult+    ( [(String, HSE.Exp HSE.SrcSpanInfo)],+      -- \^^^^^ constructor and term+      String,+      HSE.Type HSE.SrcSpanInfo+    )+parseSumDecl (HSE.Ident _ tyname) conDecls0 = do+  conDecls <- fmap Map.fromList $ traverse parseConDecl conDecls0+  let variantType = desugarVariantType $ Map.toList conDecls+  let taggedVariantType =+        -- Example:              Tagged  "Main.Person"  (Variant ..)+        --                       vvvvvv  vvvvvvvv       vvvvvvvvvvv+        HSE.TyApp l (HSE.TyApp l (hellTaggedTyCon l) (tySym qualifiedName)) variantType+  -- Note: the constructors are sorted by name, to provide a canonical ordering.+  let terms = map (makeCons conDecls variantType) $ Map.toList conDecls+  pure (terms, tyname, taggedVariantType)+  where+    l = HSE.noSrcSpan+    makeCons conDecls variantType (conName, typ)+      | HSE.TyCon _ (HSE.Qual _ (HSE.ModuleName _ "hell:Hell") (HSE.Ident _ "Nullary")) <- typ =+          ( conName,+            appTagged variantType $+              desugarVariantCon True (Map.keys conDecls) conName+          )+      | otherwise = (conName, expr)+      where+        expr =+          HSE.Lambda l [HSE.PVar l (HSE.Ident l "x")] $+            appTagged variantType $+              desugarVariantCon False (Map.keys conDecls) conName+    qualifiedName = "Main." ++ tyname+    appTagged ty =+      HSE.App l $+        HSE.App+          l+          ( HSE.App+              l+              ( HSE.App+                  l+                  (hellTaggedCon l)+                  (HSE.TypeApp l (tySym qualifiedName))+              )+              (HSE.TypeApp l ty)+          )+          ( HSE.App+              l+              (hellSSymbolCon l)+              (HSE.TypeApp l (tySym qualifiedName))+          )+    tySym s = HSE.TyPromoted l (HSE.PromotedString l s s)+parseSumDecl _ _ =+  fail "Sum type declaration not in supported format."++desugarVariantCon :: Bool -> [String] -> String -> HSE.Exp HSE.SrcSpanInfo+desugarVariantCon nullary cons thisCon = rights $ left+  where+    right _ = HSE.Var l (hellQName l "RightV")+    rights e = foldr (HSE.App l) e $ map right $ takeWhile (/= thisCon) cons+    left =+      if nullary+        then+          HSE.App+            l+            left0+            (HSE.Con l (hellQName l "Nullary"))+        else+          HSE.App+            l+            left0+            (HSE.Var l (HSE.UnQual l (HSE.Ident l "x")))+      where+        left0 =+          HSE.App+            l+            ( HSE.App+                l+                (HSE.Var l (hellQName l "LeftV"))+                (HSE.TypeApp l (tySym thisCon))+            )+            ( HSE.App+                l+                (hellSSymbolCon l)+                (HSE.TypeApp l (tySym thisCon))+            )+    tySym s = HSE.TyPromoted l (HSE.PromotedString l s s)+    l = HSE.noSrcSpan++desugarVariantType :: [(String, HSE.Type HSE.SrcSpanInfo)] -> HSE.Type HSE.SrcSpanInfo+desugarVariantType = appRecord . foldr appCons nilL+  where+    appCons (name, typ) rest =+      HSE.TyApp l (HSE.TyApp l (HSE.TyApp l consL (tySym name)) typ) rest+    appRecord x =+      HSE.TyParen l (HSE.TyApp l (hellVariantTyCon l) x)+    tySym s = HSE.TyPromoted l (HSE.PromotedString l s s)+    nilL = hellNilTyCon l+    consL = hellConsTyCon l+    l = HSE.noSrcSpan++parseConDecl :: (MonadFail f) => HSE.QualConDecl l -> f (String, HSE.Type l)+parseConDecl (HSE.QualConDecl _ Nothing Nothing (HSE.ConDecl _ (HSE.Ident _ consName) [slot])) =+  pure (consName, slot)+parseConDecl (HSE.QualConDecl l Nothing Nothing (HSE.ConDecl _ (HSE.Ident _ consName) [])) =+  pure (consName, hellTyCon l "Nullary")+parseConDecl _ = fail "Unsupported constructor declaration format."++parseDataDecl ::+  (l ~ HSE.SrcSpanInfo) =>+  HSE.Name l ->+  HSE.QualConDecl l ->+  HSE.ParseResult+    ( String,+      HSE.Exp HSE.SrcSpanInfo,+      --               ^^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^+      -- Term constructor name... and its expr.++      String,+      HSE.Type HSE.SrcSpanInfo+    )+--               ^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^^^+--          Type name... type content.+parseDataDecl (HSE.Ident _ tyname) (HSE.QualConDecl _ Nothing Nothing (HSE.RecDecl _ (HSE.Ident _ consName) fields)) = do+  -- Note: the fields are sorted by name.+  fields' <- fmap (List.sortBy (Ord.comparing fst) . concat) $ traverse getField fields+  let names = map fst fields'+  -- Technically the type checker is quite capable of handling this in+  -- a sound manner, but it's weird and Haskell disallows it, so we+  -- turn it off.+  when (List.nub names /= names) $+    fail "Field names cannot be repeated."+  let (consExpr, typ) = makeConstructor tyname fields'+  pure (consName, consExpr, tyname, typ)+  where+    getField (HSE.FieldDecl _ names typ) = do+      names' <- for names \case+        (HSE.Ident _ n) -> pure n+        _ -> fail "Invalid field name."+      pure $ map (,typ) names'+parseDataDecl _ _ =+  fail "Record declaration not in supported format."++makeConstructor ::+  String ->+  [(String, HSE.Type HSE.SrcSpanInfo)] ->+  (HSE.Exp HSE.SrcSpanInfo, HSE.Type HSE.SrcSpanInfo)+makeConstructor name fields = (appTagged recordType, taggedRecordType)+  where+    recordType = desugarRecordType fields+    taggedRecordType =+      -- Example:              Tagged  "Main.Person"  (Record ..)+      --                       vvvvvv  vvvvvvvv       vvvvvvvvvvv+      HSE.TyApp l (HSE.TyApp l (hellTaggedTyCon l) (tySym qualifiedName)) recordType+    qualifiedName = "Main." ++ name+    appTagged ty =+      HSE.App+        l+        ( HSE.App+            l+            ( HSE.App+                l+                (hellTaggedCon l)+                (HSE.TypeApp l (tySym qualifiedName))+            )+            (HSE.TypeApp l ty)+        )+        ( HSE.App+            l+            (hellSSymbolCon l)+            (HSE.TypeApp l (tySym qualifiedName))+        )+    tySym s = HSE.TyPromoted l (HSE.PromotedString l s s)+    l = HSE.noSrcSpan++makeConstructRecord :: HSE.QName HSE.SrcSpanInfo -> [HSE.FieldUpdate HSE.SrcSpanInfo] -> HSE.Exp HSE.SrcSpanInfo+makeConstructRecord qname fields =+  HSE.App l (HSE.Con l qname)+    $ foldr+      ( \(name, expr) rest ->+          let tySym s = HSE.TyPromoted l (HSE.PromotedString l s s)+           in HSE.App+                l+                ( HSE.App+                    l+                    ( HSE.App+                        l+                        (HSE.Var l (hellQName l "ConsR"))+                        ( HSE.App+                            l+                            (hellSSymbolCon l)+                            (HSE.TypeApp l (tySym name))+                        )+                    )+                    expr+                )+                rest+      )+      (HSE.Var l (hellQName l "NilR"))+    $ List.sortBy (Ord.comparing fst)+    $ map+      ( \case+          HSE.FieldUpdate _ (HSE.UnQual _ (HSE.Ident _ i)) expr -> (i, expr)+          HSE.FieldPun _ v@(HSE.UnQual _ (HSE.Ident l' i)) -> (i, HSE.Var l' v)+          f -> error $ "Invalid field: " ++ show f+      )+      fields+  where+    l = HSE.noSrcSpan++desugarRecordType :: [(String, HSE.Type HSE.SrcSpanInfo)] -> HSE.Type HSE.SrcSpanInfo+desugarRecordType = appRecord . foldr appCons nilL+  where+    appCons (name, typ) rest =+      HSE.TyApp l (HSE.TyApp l (HSE.TyApp l consL (tySym name)) typ) rest+    appRecord x =+      HSE.TyApp l (hellRecordTyCon l) x+    tySym s = HSE.TyPromoted l (HSE.PromotedString l s s)+    nilL = hellNilTyCon l+    consL = hellConsTyCon l+    l = HSE.noSrcSpan++--------------------------------------------------------------------------------+-- Typed AST support+--+-- We define a well-typed, well-indexed GADT AST which can be evaluated directly.++data Term g t where+  Var :: Var g t -> Term g t+  Lam :: Term (g, a) b -> Term g (a -> b)+  App :: Term g (s -> t) -> Term g s -> Term g t+  Lit :: a -> Term g a++data Var g t where+  ZVar :: (t -> a) -> Var (h, t) a+  SVar :: Var h t -> Var (h, s) t++--------------------------------------------------------------------------------+-- Evaluator+--++-- This is the entire evaluator. Type-safe and total.+eval :: env -> Term env t -> t+eval env (Var v) = lookp v env+eval env (Lam e) = \x -> eval (env, x) e+eval env (App e1 e2) = (eval env e1) (eval env e2)+eval _env (Lit a) = a++-- Type-safe, total lookup. The final @slot@ determines which slot of+-- a given tuple to pick out.+lookp :: Var env t -> env -> t+lookp (ZVar slot) (_, x) = slot x+lookp (SVar v) (env, _) = lookp v env++--------------------------------------------------------------------------------+-- The "untyped" AST+--+-- This is the AST that is not interpreted, and is just+-- type-checked. The HSE AST is desugared into this one.++data UTerm t+  = UVar HSE.SrcSpanInfo t String+  | ULam HSE.SrcSpanInfo t Binding (Maybe SomeStarType) (UTerm t)+  | UApp HSE.SrcSpanInfo t (UTerm t) (UTerm t)+  | USig HSE.SrcSpanInfo t (UTerm t) SomeStarType+  | -- IRep below: The variables are poly types, they aren't metavars,+    -- and need to be instantiated.+    UForall Prim HSE.SrcSpanInfo t [SomeTypeRep] Forall [TH.Uniq] (IRep TH.Uniq) [t]+  deriving (Traversable, Functor, Foldable)++typeOf :: UTerm t -> t+typeOf = \case+  UVar _ t _ -> t+  ULam _ t _ _ _ -> t+  UApp _ t _ _ -> t+  USig _ t _ _ -> t+  UForall _ _ t _ _ _ _ _ -> t++data Binding = Singleton String | Tuple [String]++data Forall where+  -- The final term, not polymorphic anymore.+  Term :: (forall g. Typed (Term g)) -> Forall+  -- forall a. ...+  Forall :: TypeRep (s :: Type) -> (forall (a :: s). TypeRep a -> Forall) -> Forall+  -- Cls a => ...+  ClassConstraint ::+    forall k (c :: k -> Constraint) (a :: k).+    TypeRep a ->+    TypeRep c ->+    ((c a) => Forall) ->+    Forall+  -- Special operators with magic type-system rules:+  GetOf ::+    TypeRep (k :: Symbol) ->+    TypeRep (a :: Type) ->+    TypeRep (t :: Symbol) ->+    TypeRep (r :: List) ->+    ((Tagged t (Record r) -> a) -> Forall) ->+    Forall+  SetOf ::+    TypeRep (k :: Symbol) ->+    TypeRep (a :: Type) ->+    TypeRep (t :: Symbol) ->+    TypeRep (r :: List) ->+    ((a -> Tagged t (Record r) -> Tagged t (Record r)) -> Forall) ->+    Forall+  ModifyOf ::+    TypeRep (k :: Symbol) ->+    TypeRep (a :: Type) ->+    TypeRep (t :: Symbol) ->+    TypeRep (r :: List) ->+    (((a -> a) -> Tagged t (Record r) -> Tagged t (Record r)) -> Forall) ->+    Forall++lit :: (Type.Typeable a) => Prim -> a -> UTerm ()+lit name = litWithSpan name HSE.noSrcSpan++litWithSpan :: (Type.Typeable a) => Prim -> HSE.SrcSpanInfo -> a -> UTerm ()+litWithSpan name srcSpanInfo l =+  litWithSpanBare name srcSpanInfo (Type.typeOf l) l++litWithSpanBare :: Prim -> HSE.SrcSpanInfo -> TypeRep a -> a -> UTerm ()+litWithSpanBare name srcSpanInfo typeRep' l =+  UForall+    name+    srcSpanInfo+    ()+    []+    (Term (Typed typeRep' (Lit l)))+    []+    (fromSomeType (SomeTypeRep typeRep'))+    []++data Prim+  = LitP (HSE.Literal HSE.SrcSpanInfo)+  | NameP String+  | UnitP+  | SSymbolP String++data SomeStarType = forall (a :: Type). SomeStarType (TypeRep a)++instance Pretty SomeStarType where+  pretty (SomeStarType a) = pretty a++deriving instance Show SomeStarType++instance Eq SomeStarType where+  SomeStarType x == SomeStarType y = Type.SomeTypeRep x == Type.SomeTypeRep y++pattern StarTypeRep t <- (toStarType -> Just (SomeStarType t))+  where+    StarTypeRep t = SomeTypeRep t++toStarType :: SomeTypeRep -> Maybe SomeStarType+toStarType (SomeTypeRep t) = do+  Type.HRefl <- Type.eqTypeRep (typeRepKind t) (typeRep @Type)+  pure $ SomeStarType t++--------------------------------------------------------------------------------+-- The type checker++data Typed (thing :: Type -> Type) = forall ty. Typed (TypeRep (ty :: Type)) (thing ty)++data TypeCheckError+  = NotInScope String+  | TupleTypeMismatch+  | TypeCheckMismatch+  | TupleTypeTooBig+  | TypeOfApplicandIsNotFunction+  | LambdaIsNotAFunBug+  | InferredCheckedDisagreeBug+  | LambdaMustBeStarBug+  | ConstraintResolutionProblem HSE.SrcSpanInfo Forall String+  deriving (Show)++instance Show Forall where show = showR++typed :: (Type.Typeable a) => a -> Typed (Term g)+typed l = Typed (Type.typeOf l) (Lit l)++-- The type environment and lookup+data TyEnv g where+  Nil :: TyEnv g+  Cons :: Binding -> TypeRep (t :: Type) -> TyEnv h -> TyEnv (h, t)++-- The top-level checker used by the main function.+check :: (UTerm SomeTypeRep) -> TyEnv () -> Either TypeCheckError (Typed (Term ()))+check = tc++-- Type check a term given an environment of names.+tc :: (UTerm SomeTypeRep) -> TyEnv g -> Either TypeCheckError (Typed (Term g))+tc (USig _l _ e (SomeStarType someStarType)) env = do+  case tc e env of+    Left err -> Left err+    Right typed'@(Typed ty _)+      | Just {} <- Type.eqTypeRep ty someStarType ->+          pure typed'+      | otherwise ->+          Left TypeCheckMismatch+tc (UVar _ _ v) env = do+  Typed ty v' <- lookupVar v env+  pure $ Typed ty (Var v')+tc (ULam _ (StarTypeRep lam_ty) s _ body) env =+  case lam_ty of+    Type.Fun bndr_ty' _+      | Just Type.HRefl <- Type.eqTypeRep (typeRepKind bndr_ty') (typeRep @Type) ->+          case tc body (Cons s bndr_ty' env) of+            Left e -> Left e+            Right (Typed body_ty' body') ->+              let checked_ty = Type.Fun bndr_ty' body_ty'+               in case Type.eqTypeRep checked_ty lam_ty of+                    Just Type.HRefl -> Right $ Typed lam_ty (Lam body')+                    Nothing -> Left InferredCheckedDisagreeBug+    _ -> Left LambdaIsNotAFunBug+tc (ULam _ (SomeTypeRep {}) _ _ _) _ =+  Left LambdaMustBeStarBug+tc (UApp _ _ e1 e2) env =+  case tc e1 env of+    Left e -> Left e+    Right (Typed (Type.Fun bndr_ty body_ty) e1') ->+      case tc e2 env of+        Left e -> Left e+        Right (Typed arg_ty e2') ->+          case Type.eqTypeRep arg_ty bndr_ty of+            Nothing ->+              Left TypeCheckMismatch+            Just (Type.HRefl) ->+              let kind = typeRepKind body_ty+               in case Type.eqTypeRep kind (typeRep @Type) of+                    Just Type.HRefl -> Right $ Typed body_ty (App e1' e2')+                    _ -> Left TypeCheckMismatch+    Right {} -> Left TypeOfApplicandIsNotFunction+-- Polytyped terms, must be, syntactically, fully-saturated+tc (UForall _ forallLoc _ _ fall _ _ reps0) _env = go reps0 fall+  where+    go :: [SomeTypeRep] -> Forall -> Either TypeCheckError (Typed (Term g))+    go [] (Term typed') = pure typed'+    go (SomeTypeRep rep : reps) (Forall sym f)+      | Just Type.HRefl <- Type.eqTypeRep (typeRepKind rep) sym = go reps (f rep)+    -- Cases that look like: Monad (Either (a :: Type) :: Type -> Type)+    go reps (ClassConstraint rep crep f) =+      withClassConstraint forallLoc reps rep crep f go+    go reps fa@(GetOf k0 a0 t0 r0 f) =+      case makeAccessor k0 r0 a0 t0 of+        Just accessor -> go reps (f accessor)+        Nothing -> problem fa $ "missing field for field access"+    go reps fa@(SetOf k0 a0 t0 r0 f) =+      case makeSetter k0 r0 a0 t0 of+        Just accessor -> go reps (f accessor)+        Nothing -> problem fa $ "missing field for field set"+    go reps fa@(ModifyOf k0 a0 t0 r0 f) =+      case makeModify k0 r0 a0 t0 of+        Just accessor -> go reps (f accessor)+        Nothing -> problem fa $ "missing field for field modify"+    go tys r = problem r $ "forall type arguments mismatch: " ++ show tys ++ " for " ++ showR r++    problem :: Forall -> String -> Either TypeCheckError a+    problem fa = Left . ConstraintResolutionProblem forallLoc fa++--------------------------------------------------------------------------------+-- Type class resolution at the call site++-- Declaration of instances (instance0, instance1, etc.) is kind-polymorphic,+-- and resolve, resolve1, etc. are kind-polymorphic. But this function IS NOT.+-- At some point you have to decide on the kinds of things. This+-- function handles a few common cases for instance head types:+--+-- Int    :: Type                           (common case)+-- []     :: Type -> Type                   (less common case)+-- Either :: Type -> Type -> Type           (rare case)+-- Mod    :: (Type -> Type) -> Type -> Type (only one example as of writing this comment)+withClassConstraint ::+  forall g k (c :: k -> Constraint) (a :: k).+  HSE.SrcSpanInfo ->+  [SomeTypeRep] ->+  TypeRep a ->+  TypeRep c ->+  ((c a) => Forall) ->+  ([SomeTypeRep] -> Forall -> Either TypeCheckError (Typed (Term g))) ->+  Either TypeCheckError (Typed (Term g))+withClassConstraint forallLoc reps rep crep f go =+  if+      -- Cases that look like: Semigroup (Vector (e :: *))+      -- Note: the kinds are limited to this exact specification in the signature above.+      | Type.App t _ <- rep,+        Just Type.HRefl <- Type.eqTypeRep (typeRepKind t) (TypeRep @(Type -> Type)),+        Just dict <- resolve1 (Type.App crep rep) crep t instances ->+          go reps (withDict dict f)+      -- Cases that look like: Monad (Either (e :: *) (a :: *))+      -- Note: the kinds are limited to this exact specification in the signature above.+      | Type.App t _ <- rep,+        Just Type.HRefl <- Type.eqTypeRep (typeRepKind t) (TypeRep @(Type -> Type -> Type)),+        Just dict <- resolve1 (Type.App crep rep) crep t instances ->+          go reps (withDict dict f)+      -- Cases that look like: Semigroup (Mod (f :: * -> *) (a :: *))+      -- Note: the kinds are limited to this exact specification in the signature above.+      | Type.App (Type.App t _a) _b <- rep,+        Just Type.HRefl <- Type.eqTypeRep (typeRepKind t) (TypeRep @((Type -> Type) -> Type -> Type)),+        Just dict <- resolve2 (Type.App crep rep) crep t instances ->+          go reps (withDict dict f)+      -- Simple cases: Eq (a :: k)+      | Just dict <- resolve crep rep instances ->+          go reps (withDict dict f)+      | otherwise ->+          problem $+            "type "+              ++ show rep+              ++ " doesn't appear to be an instance of "+              ++ show crep+  where+    problem :: forall x. String -> Either TypeCheckError x+    problem = Left . ConstraintResolutionProblem forallLoc (ClassConstraint rep crep f)++--------------------------------------------------------------------------------+-- Instances++newtype D1 c t = D1 (forall e. Dict (c (t e)))++newtype D2 c t = D2 (forall f a. Dict (c (t f a)))++newtype Instances = Instances (Map (SomeTypeRep, SomeTypeRep) Dynamic)++instances :: Instances+instances =+  Instances $+    Map.fromList+      [ instance0 @Show @Int,+        instance0 @Show @Integer,+        instance0 @Show @Day,+        instance0 @Show @UTCTime,+        instance0 @Show @TimeOfDay,+        instance0 @Show @Double,+        instance0 @Show @Bool,+        instance0 @Show @Char,+        instance0 @Show @Text,+        instance0 @Show @ByteString,+        instance0 @Show @ExitCode,+        instance0 @Eq @Int,+        instance0 @Eq @Integer,+        instance0 @Eq @Day,+        instance0 @Eq @UTCTime,+        instance0 @Eq @TimeOfDay,+        instance0 @Eq @Double,+        instance0 @Eq @Bool,+        instance0 @Eq @Char,+        instance0 @Eq @Text,+        instance0 @Eq @ByteString,+        instance0 @Eq @ExitCode,+        instance0 @Ord @Int,+        instance0 @Ord @Integer,+        instance0 @Ord @Day,+        instance0 @Ord @UTCTime,+        instance0 @Ord @TimeOfDay,+        instance0 @Ord @Double,+        instance0 @Ord @Bool,+        instance0 @Ord @Char,+        instance0 @Ord @Text,+        instance0 @Ord @ByteString,+        instance0 @Ord @ExitCode,+        instance0 @Monad @IO,+        instance0 @Monad @Maybe,+        instance0 @Monad @[],+        instance0 @Monad @Tree,+        instance1 @Monad @Either,+        instance0 @Functor @IO,+        instance0 @Functor @Maybe,+        instance0 @Functor @[],+        instance0 @Functor @Tree,+        instance0 @Functor @Options.Parser,+        instance1 @Functor @Either,+        instance0 @Applicative @IO,+        instance0 @Applicative @Maybe,+        instance0 @Applicative @[],+        instance0 @Applicative @Tree,+        instance0 @Applicative @Options.Parser,+        instance1 @Applicative @Either,+        instance0 @Alternative @Options.Parser,+        instance0 @Alternative @Maybe,+        instance0 @Monoid @Text,+        instance1 @Monoid @Vector,+        instance2 @Monoid @Options.Mod,+        instance1 @Monoid @[],+        instance2 @Semigroup @Options.Mod,+        instance0 @Semigroup @Text,+        instance1 @Semigroup @Vector,+        instance1 @Semigroup @[]+      ]++--------------------------------------------------------------------------------+-- Instance declarations++instance0 ::+  forall cls a.+  (cls a, Typeable cls, Typeable a) =>+  ((SomeTypeRep, SomeTypeRep), Dynamic)+instance0 =+  ( (SomeTypeRep $ typeRep @cls, SomeTypeRep $ typeRep @a),+    toDyn $ Dict @(cls a)+  )++instance1 ::+  forall {k0} {k1} (c :: k1 -> Constraint) (t :: k0 -> k1).+  ((forall a. c (t a)), Typeable c, Typeable t, Typeable k0, Typeable k1) =>+  ((SomeTypeRep, SomeTypeRep), Dynamic)+instance1 =+  ( (SomeTypeRep $ typeRep @c, SomeTypeRep $ typeRep @t),+    toDyn $ D1 @c @t Dict+  )++instance2 ::+  forall {k0} {k1} {k2} (c :: k2 -> Constraint) (t :: k0 -> k1 -> k2).+  ((forall a b. c (t a b)), Typeable c, Typeable t, Typeable k0, Typeable k1, Typeable k2) =>+  ((SomeTypeRep, SomeTypeRep), Dynamic)+instance2 =+  ( (SomeTypeRep $ typeRep @c, SomeTypeRep $ typeRep @t),+    toDyn $ D2 @c @t Dict+  )++--------------------------------------------------------------------------------+-- Instance resolution++-- Resolve an instance of the form: Eq a+resolve :: TypeRep c -> TypeRep (a :: k) -> Instances -> Maybe (Dict (c a))+resolve c a (Instances m) = do+  Dynamic rep dict <- Map.lookup (SomeTypeRep c, SomeTypeRep a) m+  Type.HRefl <- Type.eqTypeRep rep (Type.App (TypeRep @Dict) (Type.App c a))+  pure dict++-- Resolve an instance of the form: Monad (Either e)+resolve1 ::+  forall {k0} {k1} (t :: k0 -> k1) (c :: k1 -> Constraint) (a :: k0).+  (Typeable k0, Typeable k1) =>+  TypeRep (c (t a)) ->+  TypeRep c ->+  TypeRep t ->+  Instances ->+  Maybe (Dict (c (t a)))+resolve1 _ c t (Instances m) = do+  Dynamic rep dict <- Map.lookup (SomeTypeRep c, SomeTypeRep t) m+  Type.HRefl <- Type.eqTypeRep rep $ Type.App (Type.App (typeRep @D1) c) t+  let D1 d = dict+  pure d++-- Resolve an instance of the form: Monoid (Mod f a)+resolve2 ::+  forall {k0} {k1} {k2} (t :: k0 -> k1 -> k2) (c :: k2 -> Constraint) (a :: k0) (b :: k1).+  (Typeable k0, Typeable k1, Typeable k2) =>+  TypeRep (c (t a b)) ->+  TypeRep c ->+  TypeRep t ->+  Instances ->+  Maybe (Dict (c (t a b)))+resolve2 _ c t (Instances m) = do+  Dynamic rep dict <- Map.lookup (SomeTypeRep c, SomeTypeRep t) m+  Type.HRefl <- Type.eqTypeRep rep $ Type.App (Type.App (typeRep @D2) c) t+  let D2 d = dict+  pure d++--------------------------------------------------------------------------------++showR :: Forall -> String+showR = \case+  Forall ty _ -> "forall s. s :: " <> prettyString ty+  ClassConstraint t c _ -> prettyString c <> " (" <> prettyString t <> ")"+  Term _ -> "<term>"+  GetOf {} -> "<record getter>"+  SetOf {} -> "<record setter>"+  ModifyOf {} -> "<record modifier>"++-- Make a well-typed literal - e.g. @lit Text.length@ - which can be+-- embedded in the untyped AST.+lookupVar :: String -> TyEnv g -> Either TypeCheckError (Typed (Var g))+lookupVar str Nil = Left $ NotInScope str+lookupVar v (Cons (Singleton s) ty e)+  | v == s = pure $ Typed ty (ZVar id)+  | otherwise = do+      Typed ty' v' <- lookupVar v e+      pure $ Typed ty' (SVar v')+lookupVar v (Cons (Tuple ss) ty e)+  | Just i <- lookup v $ zip ss [0 :: Int ..] =+      case ty of+        Type.App (Type.App tup x) y+          | Just Type.HRefl <- Type.eqTypeRep tup (typeRep @(,)) ->+              case i of+                0 -> pure $ Typed x $ ZVar \(a, _) -> a+                1 -> pure $ Typed y $ ZVar \(_, b) -> b+                _ -> Left TupleTypeMismatch+        Type.App (Type.App (Type.App tup x) y) z+          | Just Type.HRefl <- Type.eqTypeRep tup (typeRep @(,,)) ->+              case i of+                0 -> pure $ Typed x $ ZVar \(a, _, _) -> a+                1 -> pure $ Typed y $ ZVar \(_, b, _) -> b+                2 -> pure $ Typed z $ ZVar \(_, _, c) -> c+                _ -> Left TupleTypeMismatch+        Type.App (Type.App (Type.App (Type.App tup x) y) z) z'+          | Just Type.HRefl <- Type.eqTypeRep tup (typeRep @(,,,)) ->+              case i of+                0 -> pure $ Typed x $ ZVar \(a, _, _, _) -> a+                1 -> pure $ Typed y $ ZVar \(_, b, _, _) -> b+                2 -> pure $ Typed z $ ZVar \(_, _, c, _) -> c+                3 -> pure $ Typed z' $ ZVar \(_, _, _, d) -> d+                _ -> Left TupleTypeMismatch+        _ -> Left TupleTypeTooBig+  | otherwise = do+      Typed ty' v' <- lookupVar v e+      pure $ Typed ty' (SVar v')++--------------------------------------------------------------------------------+-- Desugar expressions++data DesugarError+  = InvalidConstructor String+  | InvalidVariable String+  | UnknownType String+  | UnsupportedSyntax String+  | BadParameterSyntax String+  | KindError+  | BadDoNotation+  | TupleTooBig+  | UnsupportedLiteral+  deriving (Show, Eq)++nestedTyApps :: HSE.Exp HSE.SrcSpanInfo -> Maybe (HSE.QName HSE.SrcSpanInfo, [HSE.Type HSE.SrcSpanInfo])+nestedTyApps = go []+  where+    go acc (HSE.App _ (HSE.Var _ qname) (HSE.TypeApp _ ty)) = pure (qname, ty : acc)+    go acc (HSE.App _ (HSE.Con _ qname) (HSE.TypeApp _ ty)) = pure (qname, ty : acc)+    go acc (HSE.App _ e (HSE.TypeApp _ ty)) = go (ty : acc) e+    go _ _ = Nothing++desugarExp ::+  Map String SomeTypeRep ->+  Map String (UTerm ()) ->+  HSE.Exp HSE.SrcSpanInfo ->+  Either DesugarError (UTerm ())+desugarExp userDefinedTypeAliases globals = go mempty+  where+    go scope = \case+      HSE.ExpTypeSig l e ty -> do+        e' <- go scope e+        ty' <- desugarStarType userDefinedTypeAliases ty+        pure $ USig l () e' ty'+      HSE.Case l e alts -> do+        e' <- desugarCase l e alts+        go scope e'+      HSE.Paren _ x -> go scope x+      HSE.If l i t e ->+        (\e' t' i' -> UApp l () (UApp l () (UApp l () (bool' l) e') t') i')+          <$> go scope e+          <*> go scope t+          <*> go scope i+      HSE.Tuple l HSE.Boxed xs -> do+        xs' <- traverse (go scope) xs+        pure $ foldl (UApp l ()) (tuple' (length xs) l) xs'+      HSE.List l xs -> do+        xs' <- traverse (go scope) xs+        pure $ foldr (\x y -> UApp l () (UApp l () (cons' l) x) y) (nil' l) xs'+      HSE.Lit _ lit' -> case lit' of+        HSE.Char _ char _ -> pure $ lit (LitP lit') char+        HSE.String _ string _ -> pure $ lit (LitP lit') $ Text.pack string+        HSE.Int _ int _ -> pure $ lit (LitP lit') (fromIntegral int :: Int)+        HSE.Frac _ _ str+          | Just dub <- Read.readMaybe str ->+              pure $ lit (LitP lit') (dub :: Double)+        _ -> Left $ UnsupportedLiteral+      HSE.App l ssymbol typeapp+        | void ssymbol == hellSSymbolCon (),+          HSE.TypeApp _ (HSE.TyPromoted _ (HSE.PromotedString _ string _)) <- typeapp ->+            withSomeSSymbol string \(sym@(SSymbol :: SSymbol s)) ->+              pure $+                litWithSpanBare+                  (SSymbolP string)+                  l+                  (typeRep @(SSymbol s))+                  sym+      app@HSE.App {} | Just (qname, tys) <- nestedTyApps app -> do+        reps <- traverse (desugarSomeType userDefinedTypeAliases) tys+        desugarQName scope globals qname reps+      HSE.Var _ qname ->+        desugarQName scope globals qname []+      HSE.App l f x -> UApp l () <$> go scope f <*> go scope x+      HSE.InfixApp l x (HSE.QVarOp l'op f) y -> UApp l () <$> (UApp l'op () <$> go scope (HSE.Var l'op f) <*> go scope x) <*> go scope y+      HSE.Lambda l pats e -> do+        args <- traverse (desugarArg userDefinedTypeAliases) pats+        let stringArgs = concatMap (bindingStrings . fst) args+        e' <- go (foldr Set.insert scope stringArgs) e+        pure $ foldr (\(name, ty) inner -> ULam l () name ty inner) e' args+      HSE.Con _ qname ->+        desugarQName scope globals qname []+      HSE.Do _ stmts -> do+        let squash [HSE.Qualifier _ e] = pure e+            squash (s : ss) = do+              case s of+                HSE.Generator l pat e -> do+                  inner <- squash ss+                  let (.>>=) = HSE.Var l (HSE.Qual l (HSE.ModuleName l "Monad") (HSE.Ident l "bind"))+                  pure $+                    HSE.App+                      l+                      (HSE.App l (.>>=) e)+                      (HSE.Lambda l [pat] inner)+                HSE.Qualifier l e -> do+                  inner <- squash ss+                  let (.>>) = HSE.Var l (HSE.Qual l (HSE.ModuleName l "Monad") (HSE.Ident l "then"))+                  pure $+                    HSE.App+                      l+                      (HSE.App l (.>>) e)+                      inner+                HSE.LetStmt l (HSE.BDecls _ [HSE.PatBind _ pat (HSE.UnGuardedRhs _ e) Nothing]) -> do+                  inner <- squash ss+                  pure $ HSE.App l (HSE.Lambda l [pat] inner) e+                _ -> Left BadDoNotation+            squash _ = Left BadDoNotation+        squash stmts >>= go scope+      HSE.RecConstr _ qname fields -> go scope $ makeConstructRecord qname fields+      e -> Left $ UnsupportedSyntax $ show e++-- | Handles both user-defined case and primitive type case (Maybe, Either, etc.)+desugarCase+  :: HSE.SrcSpanInfo+  -> HSE.Exp HSE.SrcSpanInfo+  -> [HSE.Alt HSE.SrcSpanInfo]+  -> Either DesugarError (HSE.Exp HSE.SrcSpanInfo)+desugarCase _ _ [] = Left $ UnsupportedSyntax "empty case"+-- Generates this:+--+-- Either.either (\a -> e1 a) (\b -> e2 b) scrutinee+-- Maybe.maybe e1 (\b -> e2 b) scrutinee+-- etc+desugarCase l scrutinee alts0 | any isPrimCons alts0 = do+  let (wilds, alts) =+        Either.partitionEithers $+          map (\x -> maybe (Right x) Left $ desugarWildPat x) alts0+  conses <- traverse desugarPrimCons alts+  let names = map (.accessor) conses+  let consNames = map (.constructor) conses+  let mwildpat = Maybe.listToMaybe wilds+  if+    | length wilds > 1 ->+       Left $ UnsupportedSyntax $+         "at most one catch-all (var/wildcard) in a case is permitted"+    | Set.toList (Set.fromList consNames) /= List.sort consNames ->+       Left $ UnsupportedSyntax $ "duplicate constructors in case: " <>+         show consNames+         <> show consNames+     -- | All constructors below to the same type.+    | Set.size (Set.fromList names) == 1 ->+      HSE.App l <$> desugarPrimAlts l (List.concat (take 1 names)) conses mwildpat+                <*> pure scrutinee+    | otherwise ->+      Left $ UnsupportedSyntax $ "mismatching types for constructors in case: "+         <> show consNames+-- Generates this:+--+-- Variant.run+--           x+--           $ Variant.cons @"Main.Number" (\i -> Show.show i) $+--              Variant.cons @"Main.Text" (\t -> t) $+--                Variant.nil (or `WildP x' for `_ -> x')+desugarCase l scrutinee xs = do+  alts0 <- fmap (List.sortBy (Ord.comparing fst)) $ traverse desugarAlt xs+  let (alts,wild0) = Either.partitionEithers $+        map (\(x,y) -> bimap (const y) (const y) x) alts0+  if length wild0 > 1+    then+      Left $ UnsupportedSyntax $+           "at most one catch-all (var/wildcard) in a case is permitted"+    else do+      let wild = Maybe.listToMaybe wild0+      pure $+        HSE.App l (HSE.App l run scrutinee) $+          foldr (HSE.App l) (Maybe.fromMaybe nil wild) alts+  where+    tySym s = HSE.TyPromoted l (HSE.PromotedString l s s)+    nil =+      ( HSE.Var+          l+          ( hellQName l "NilA"+          )+      )+    run =+      ( HSE.Var+          l+          (hellQName l "runAccessor")+      )+    desugarAlt+      ( HSE.Alt+          l'+          ( HSE.PApp+              _+              (HSE.UnQual _ (HSE.Ident _ name))+              [HSE.PVar _ (HSE.Ident _ x)]+            )+          (HSE.UnGuardedRhs _ e)+          Nothing+        ) =+        -- Variant.cons @name (\x -> e)+        pure $+          (Left name,) $+            HSE.App+              l'+              ( HSE.App+                  l'+                  ( HSE.Var+                      l'+                      (hellQName l' "ConsA")+                  )+                  (HSE.TypeApp l' (tySym name))+              )+              (HSE.Lambda l' [HSE.PVar l' (HSE.Ident l' x)] e)+    -- Nullary constructor+    desugarAlt+      ( HSE.Alt+          l'+          ( HSE.PApp+              _+              (HSE.UnQual _ (HSE.Ident _ name))+              []+            )+          (HSE.UnGuardedRhs _ e)+          Nothing+        ) =+        -- Variant.cons @name (\_ -> e)+        pure $+          (Left name,) $+            HSE.App+              l'+              ( HSE.App+                  l'+                  ( HSE.Var+                      l'+                      (hellQName l' "ConsA")+                  )+                  (HSE.TypeApp l' (tySym name))+              )+              (HSE.Lambda l' [HSE.PVar l' (HSE.Ident l' "_")] e)+    desugarAlt (HSE.Alt l' (HSE.PWildCard l1) (HSE.UnGuardedRhs _ e) Nothing) =+      pure $ (Right (), HSE.App+         l'+         ( HSE.Var+             l1+             (hellQName l' "WildA")+         )+         e)+    desugarAlt _ = Left $ UnsupportedSyntax "case alternative syntax"++data PrimCons = PrimCons {+  l :: HSE.SrcSpanInfo,+  accessor :: String,+  constructor :: String,+  bindings :: [String],+  rhs :: HSE.Exp HSE.SrcSpanInfo+  } deriving (Show)++data WildPat = WildPat {+  l :: HSE.SrcSpanInfo,+  rhs :: HSE.Exp HSE.SrcSpanInfo+  } deriving (Show)++desugarPrimCons+  :: HSE.Alt HSE.SrcSpanInfo+  -> Either DesugarError PrimCons+desugarPrimCons (HSE.Alt l (HSE.PApp _ qname slots) (HSE.UnGuardedRhs _ rhs) Nothing)+  | HSE.Qual _ (HSE.ModuleName _ prefix) (HSE.Ident _ string) <- qname,+    let constructor = (prefix ++ "." ++ string),+    Just (accessor,arity) <- Map.lookup constructor primitiveConstructors =+  if length slots /= arity+      then Left $ UnsupportedSyntax $ "wrong number of arguments to constructor in case alt: " ++ string+      else do bindings <- traverse desugarPVarIdent slots+              pure PrimCons{l, accessor, constructor, bindings, rhs}+  where+    desugarPVarIdent (HSE.PVar _ (HSE.Ident _ i)) = pure i+    desugarPVarIdent _ =+      Left $+        UnsupportedSyntax "only var patterns are allowed in a primitive case (for now)"+desugarPrimCons (HSE.Alt _ p _ _) =+  Left $ UnsupportedSyntax $+    "unknown primitive constructor in pat: " <> HSE.prettyPrint p++desugarWildPat+  :: HSE.Alt HSE.SrcSpanInfo+  -> Maybe WildPat+desugarWildPat (HSE.Alt _ (HSE.PWildCard l) (HSE.UnGuardedRhs _ rhs) Nothing) =+  Just WildPat { l, rhs }+desugarWildPat _ = Nothing++isPrimCons :: HSE.Alt HSE.SrcSpanInfo -> Bool+isPrimCons (HSE.Alt _ (HSE.PApp _ qname _) _ _)+  | HSE.Qual _ (HSE.ModuleName _ prefix) (HSE.Ident _ string) <- qname =+  Map.member (prefix ++ "." ++ string) primitiveConstructors+isPrimCons _ = False++desugarPrimAlts+  :: HSE.SrcSpanInfo+  -> String -- ^ Accessor e.g. Maybe.maybe+  -> [PrimCons] -- ^ (cons, bindings, rhs)+  -> Maybe WildPat+  -> Either DesugarError (HSE.Exp HSE.SrcSpanInfo)+desugarPrimAlts l accessor consesFound mwildpat =+  case lookup accessor primitiveSumTypes of+    Nothing -> Left $ UnsupportedSyntax $ "invalid primitive accessor " <> accessor+    Just cases -> do+      alts <- traverse makeAlt cases+      pure $  foldl' (HSE.App l) accessorE alts+  where+    accessorE =+      HSE.Var l (HSE.Qual l (HSE.ModuleName l prefix) (HSE.Ident l string))+    (prefix,drop 1 -> string) = List.break (=='.') accessor+    makeAlt (cons, arity) =+      case find ((==cons) . (.constructor)) consesFound of+        Nothing ->+          case mwildpat of+            Nothing ->+              Left $ UnsupportedSyntax $ "missing constructor in case: " <> cons+            Just wildpat ->+              pure $ HSE.Lambda+                wildpat.l+                pats+                wildpat.rhs+              where pats = [ HSE.PWildCard wildpat.l+                           | _ <- [1.. arity] ]+        Just primCons ->+          pure $ HSE.Lambda+            primCons.l+            pats+            primCons.rhs+          where pats = [ HSE.PVar primCons.l (HSE.Ident primCons.l b)+                       | b <- primCons.bindings ]++bindingStrings :: Binding -> [String]+bindingStrings (Singleton string) = [string]+bindingStrings (Tuple tups) = tups++desugarQName :: Set String -> Map String (UTerm ()) -> HSE.QName HSE.SrcSpanInfo -> [SomeTypeRep] -> Either DesugarError (UTerm ())+desugarQName scope globals qname [] =+  case qname of+    HSE.UnQual _ (HSE.Ident l string) | Set.member string scope -> pure $ UVar l () string+    HSE.Qual _ (HSE.ModuleName _ "Main") (HSE.Ident _ string)+      | Just uterm <- Map.lookup string globals ->+          pure uterm+    HSE.Qual _ (HSE.ModuleName _ prefix) (HSE.Ident _ string)+      | Just (uterm, _) <- Map.lookup (prefix ++ "." ++ string) supportedLits ->+          pure $ uterm+    HSE.UnQual _ (HSE.Symbol _ string)+      | Just (uterm, _) <- Map.lookup string supportedLits ->+          pure $ uterm+    _ -> desugarPolyQName qname []+desugarQName _ _ qname treps = desugarPolyQName qname treps++desugarPolyQName :: HSE.QName HSE.SrcSpanInfo -> [SomeTypeRep] -> Either DesugarError (UTerm ())+desugarPolyQName qname treps =+  case qname of+    HSE.Qual l (HSE.ModuleName _ prefix) (HSE.Ident _ string)+      | let namep = (prefix ++ "." ++ string),+        Just (forall', vars, irep, _) <- Map.lookup namep polyLits -> do+          pure (UForall (NameP namep) l () treps forall' vars irep [])+    HSE.UnQual l (HSE.Symbol _ string)+      | let namep = string,+        Just (forall', vars, irep, _) <- Map.lookup string polyLits -> do+          pure (UForall (NameP namep) l () treps forall' vars irep [])+    HSE.Special l (HSE.UnitCon {}) ->+      pure $ litWithSpan UnitP l ()+    _ -> Left $ InvalidVariable $ show qname++desugarArg :: Map String SomeTypeRep -> HSE.Pat HSE.SrcSpanInfo -> Either DesugarError (Binding, Maybe SomeStarType)+desugarArg userDefinedTypeAliases (HSE.PatTypeSig _ (HSE.PVar _ (HSE.Ident _ i)) typ) =+  fmap (Singleton i,) (fmap Just (desugarStarType userDefinedTypeAliases typ))+desugarArg userDefinedTypeAliases (HSE.PatTypeSig _ (HSE.PTuple _ HSE.Boxed idents) typ)+  | Just idents' <- traverse desugarIdent idents =+      fmap (Tuple idents',) (fmap Just (desugarStarType userDefinedTypeAliases typ))+desugarArg _ (HSE.PVar _ (HSE.Ident _ i)) =+  pure (Singleton i, Nothing)+desugarArg _ (HSE.PTuple _ HSE.Boxed idents)+  | Just idents' <- traverse desugarIdent idents =+      pure (Tuple idents', Nothing)+desugarArg userDefinedTypeAliases (HSE.PParen _ p) = desugarArg userDefinedTypeAliases p+desugarArg _ (HSE.PWildCard l) =+  pure $ (Singleton $+    "$wildcard_" <> show (HSE.startLine l) <> "_" <> show (HSE.startColumn l),+    Nothing)+desugarArg _ p = Left $ BadParameterSyntax $ HSE.prettyPrint p++desugarIdent :: HSE.Pat HSE.SrcSpanInfo -> Maybe String+desugarIdent (HSE.PVar _ (HSE.Ident _ s)) = Just s+desugarIdent _ = Nothing++--------------------------------------------------------------------------------+-- Desugar types++desugarStarType :: Map String SomeTypeRep -> HSE.Type HSE.SrcSpanInfo -> Either DesugarError SomeStarType+desugarStarType userDefinedTypeAliases t = do+  someRep <- desugarSomeType userDefinedTypeAliases t+  case someRep of+    StarTypeRep t' -> pure (SomeStarType t')+    _ -> Left KindError++desugarSomeType ::+  Map String SomeTypeRep ->+  HSE.Type HSE.SrcSpanInfo ->+  Either DesugarError SomeTypeRep+desugarSomeType userDefinedTypeAliases = go+  where+    go :: HSE.Type HSE.SrcSpanInfo -> Either DesugarError SomeTypeRep+    go = \case+      HSE.TyTuple _ HSE.Boxed types -> do+        tys <- traverse go types+        case tys of+          [StarTypeRep a, StarTypeRep b] ->+            pure $ StarTypeRep (Type.App (Type.App (typeRep @(,)) a) b)+          [StarTypeRep a, StarTypeRep b, StarTypeRep c] ->+            pure $ StarTypeRep (Type.App (Type.App (Type.App (typeRep @(,,)) a) b) c)+          [StarTypeRep a, StarTypeRep b, StarTypeRep c, StarTypeRep d] ->+            pure $ StarTypeRep (Type.App (Type.App (Type.App (Type.App (typeRep @(,,,)) a) b) c) d)+          _ -> Left TupleTooBig+      HSE.TyParen _ x -> go x+      HSE.TyCon _ (HSE.UnQual _ (HSE.Ident _ name))+        | Just rep <- Map.lookup name supportedTypeConstructors -> pure rep+      HSE.TyCon _ (HSE.Qual _ (HSE.ModuleName _ m) (HSE.Ident _ name))+        | Just rep <- Map.lookup (m <> "." <> name) (supportedTypeConstructors <> userDefinedTypeAliases) ->+            pure rep+      HSE.TyCon _ (HSE.Special _ HSE.UnitCon {}) -> pure $ StarTypeRep $ typeRep @()+      HSE.TyList _ inner -> do+        rep <- go inner+        case rep of+          StarTypeRep t' -> pure $ StarTypeRep $ Type.App (typeRep @[]) t'+          _ -> Left KindError+      HSE.TyFun _ a b -> do+        a' <- go a+        b' <- go b+        case (a', b') of+          (StarTypeRep aRep, StarTypeRep bRep) ->+            pure $ StarTypeRep (Type.Fun aRep bRep)+          _ -> Left KindError+      HSE.TyApp _ f a -> do+        f' <- go f+        a' <- go a+        case applyTypes f' a' of+          Just someTypeRep -> pure someTypeRep+          _ -> Left KindError+      HSE.TyPromoted _ (HSE.PromotedString _ string _) ->+        case someSymbolVal string of+          SomeSymbol p ->+            pure $ Type.someTypeRep p+      -- TODO: Remove later.+      HSE.TyPromoted _ (HSE.PromotedCon _ _bool (HSE.UnQual _ (HSE.Ident _ name)))+        | Just rep <- Map.lookup name supportedTypeConstructors -> pure rep+      t' -> Left $ UnknownType $ show t'++-- | Apply a type `f' with an argument `x', if it is a type function,+-- and the input is the right kind.+applyTypes :: SomeTypeRep -> SomeTypeRep -> Maybe SomeTypeRep+applyTypes (SomeTypeRep f) (SomeTypeRep x) =+  case Type.typeRepKind f of+    Type.App (Type.App (-->) a) _b+      | Just Type.HRefl <- Type.eqTypeRep (-->) (TypeRep @(->)) ->+          case Type.eqTypeRep (Type.typeRepKind x) a of+            Just Type.HRefl ->+              Just $ SomeTypeRep $ Type.App f x+            _ -> Nothing+    _ -> Nothing++--------------------------------------------------------------------------------+-- Desugar all bindings++desugarAll ::+  [(String, HSE.Type HSE.SrcSpanInfo)] ->+  [(String, HSE.Exp HSE.SrcSpanInfo)] ->+  Either DesugarError [(String, UTerm ())]+desugarAll types0 terms0 = do+  types <-+    flip execStateT Map.empty $+      traverse goType $+        Graph.flattenSCCs $+          stronglyConnected $+            types0+  terms <-+    flip evalStateT Map.empty $+      traverse (goTerm types) $+        Graph.flattenSCCs $+          stronglyConnected $+            terms0+  pure terms+  where+    goTerm ::+      Map String SomeTypeRep ->+      (String, HSE.Exp HSE.SrcSpanInfo) ->+      StateT (Map String (UTerm ())) (Either DesugarError) (String, UTerm ())+    goTerm userDefinedTypeAliases (name, expr) = do+      globals <- get+      uterm <- lift $ desugarExp userDefinedTypeAliases globals expr+      modify' $ Map.insert name uterm+      pure (name, uterm)++    goType ::+      (String, HSE.Type HSE.SrcSpanInfo) ->+      StateT (Map String SomeTypeRep) (Either DesugarError) ()+    goType (name, typ) = do+      types <- get+      SomeStarType someTypeRep <- lift $ desugarStarType types typ+      modify' $ Map.insert ("Main." ++ name) $ SomeTypeRep someTypeRep++--------------------------------------------------------------------------------+-- Infer++data InferError+  = UnifyError UnifyError+  | ZonkError ZonkError+  | ElabError ElaborateError+  deriving (Show)++-- | Note: All types in the input are free of metavars. There is an+-- intermediate phase in which there are metavars, but then they're+-- all eliminated. By the type system, the output contains only+-- determinate types.+inferExp ::+  StatsEnabled ->+  UTerm () ->+  IO (Either InferError (UTerm SomeTypeRep))+inferExp stats uterm = do+  t0 <- getTime+  case elaborate uterm of+    Left elabError -> pure $ Left $ ElabError elabError+    Right (iterm, equalities) -> do+      t1 <- getTime+      emitStat stats "elaborate" (t1 - t0)+      case unify equalities of+        Left unifyError -> pure $ Left $ UnifyError unifyError+        Right subs -> do+          t2 <- getTime+          emitStat stats "unify" (t2 - t1)+          case traverse (zonkToStarType subs) iterm of+            Left zonkError -> pure $ Left $ ZonkError $ zonkError+            Right !sterm -> do+              t3 <- getTime+              emitStat stats "zonk" (t3 - t2)+              pure $ Right sterm++-- | Zonk a type and then convert it to a type: t :: *+zonkToStarType :: Map IMetaVar (IRep IMetaVar) -> IRep IMetaVar -> Either ZonkError SomeTypeRep+zonkToStarType subs irep = do+  zonked <- zonk (substitute subs irep)+  toSomeTypeRep zonked++--------------------------------------------------------------------------------+-- Occurs check++anyCycles :: (SYB.Data a) => [(String, a)] -> Bool+anyCycles =+  any isCycle+    . stronglyConnected+  where+    isCycle = \case+      Graph.CyclicSCC {} -> True+      _ -> False++stronglyConnected :: (SYB.Data a) => [(String, a)] -> [Graph.SCC (String, a)]+stronglyConnected =+  Graph.stronglyConnComp+    . map \thing@(name, e) -> (thing, name, freeVariables e)++--------------------------------------------------------------------------------+-- Get free variables of an HSE expression++freeVariables :: (SYB.Data a) => a -> [String]+freeVariables =+  Maybe.mapMaybe unpack+    . SYB.listify (const True :: HSE.QName HSE.SrcSpanInfo -> Bool)+  where+    unpack = \case+      HSE.Qual _ (HSE.ModuleName _ "Main") (HSE.Ident _ name) -> pure name+      _ -> Nothing++--------------------------------------------------------------------------------+-- Supported type constructors++supportedTypeConstructors :: Map String SomeTypeRep+supportedTypeConstructors =+  Map.fromList+    [ -- Standard Haskell types+      ("Bool", SomeTypeRep $ typeRep @Bool),+      ("Int", SomeTypeRep $ typeRep @Int),+      ("Integer", SomeTypeRep $ typeRep @Integer),+      ("Double", SomeTypeRep $ typeRep @Double),+      ("Char", SomeTypeRep $ typeRep @Char),+      ("Text", SomeTypeRep $ typeRep @Text),+      ("Map", SomeTypeRep $ typeRep @Map),+      ("ByteString", SomeTypeRep $ typeRep @ByteString),+      ("ExitCode", SomeTypeRep $ typeRep @ExitCode),+      ("Maybe", SomeTypeRep $ typeRep @Maybe),+      ("Either", SomeTypeRep $ typeRep @Either),+      ("IO", SomeTypeRep $ typeRep @IO),+      ("Vector", SomeTypeRep $ typeRep @Vector),+      ("Set", SomeTypeRep $ typeRep @Set),+      ("These", SomeTypeRep $ typeRep @These),+      ("Tree", SomeTypeRep $ typeRep @Tree),+      ("Value", SomeTypeRep $ typeRep @Value),+      ("()", SomeTypeRep $ typeRep @()),+      ("Handle", SomeTypeRep $ typeRep @IO.Handle),+      ("Day", SomeTypeRep $ typeRep @Day),+      ("UTCTime", SomeTypeRep $ typeRep @UTCTime),+      ("TimeOfDay", SomeTypeRep $ typeRep @TimeOfDay),+      -- Internal, hidden types+      ("hell:Hell.NilL", SomeTypeRep $ typeRep @('NilL)),+      ("hell:Hell.ConsL", SomeTypeRep $ typeRep @('ConsL)),+      ("hell:Hell.Variant", SomeTypeRep $ typeRep @Variant),+      ("hell:Hell.Record", SomeTypeRep $ typeRep @Record),+      ("hell:Hell.Tagged", SomeTypeRep $ typeRep @Tagged),+      ("hell:Hell.Nullary", SomeTypeRep $ typeRep @Nullary)+    ]++-- | Used for constructors with no slot. E.g. True :: Nullary -> Bool+data Nullary = Nullary++--------------------------------------------------------------------------------+-- Support primitives++supportedLits :: Map String (UTerm (), SomeTypeRep)+supportedLits =+  Map.fromList+    [ -- Text I/O+      lit' "Text.putStrLn" t_putStrLn,+      lit' "Text.hPutStr" t_hPutStr,+      lit' "Text.putStr" t_putStr,+      lit' "Text.getLine" t_getLine,+      lit' "Text.writeFile" t_writeFile,+      lit' "Text.readFile" t_readFile,+      lit' "Text.appendFile" t_appendFile,+      lit' "Text.readProcess" t_readProcess,+      lit' "Text.readProcess_" t_readProcess_,+      lit' "Text.readProcessStdout_" t_readProcessStdout_,+      lit' "Text.getContents" (fmap Text.decodeUtf8 ByteString.getContents),+      lit' "Text.setStdin" t_setStdin,+      -- Dates+      lit' "Day.fromGregorianValid" Time.fromGregorianValid,+      lit' "Day.addDays" Time.addDays,+      lit' "Day.diffDays" Time.diffDays,+      lit' "Day.iso8601Show" (Text.pack . Time.iso8601Show :: Day -> Text),+      lit' "Day.iso8601ParseM" (Time.iso8601ParseM . Text.unpack :: Text -> Maybe Day),+      -- UTCTime+      --+      -- We're going to skip NominalDiffTime, DiffTime, etc. and thus+      -- put a hard limit on dealing with leap-seconds in Hell+      -- scripts.+      --+      lit' "UTCTime.UTCTime" (\d (t :: Double) -> Time.UTCTime d (realToFrac t)),+      lit' "UTCTime.utctDay" Time.utctDay,+      lit' "UTCTime.utctDayTime" (realToFrac . Time.utctDayTime :: UTCTime -> Double),+      lit' "UTCTime.addUTCTime" \(d :: Double) t -> Time.addUTCTime (realToFrac d) t,+      lit' "UTCTime.diffUTCTime" \a b -> realToFrac (Time.diffUTCTime a b) :: Double,+      lit' "UTCTime.getCurrentTime" Time.getCurrentTime,+      lit' "UTCTime.iso8601Show" (Text.pack . Time.iso8601Show :: UTCTime -> Text),+      lit' "UTCTime.iso8601ParseM" (Time.iso8601ParseM . Text.unpack :: Text -> Maybe UTCTime),+      -- TimeOfDay+      lit' "TimeOfDay.timeToTimeOfDay" (Time.timeToTimeOfDay . realToFrac :: Double -> TimeOfDay),+      lit' "TimeOfDay.todHour" Time.todHour,+      lit' "TimeOfDay.todMin" Time.todMin,+      lit' "TimeOfDay.todSec" (realToFrac . Time.todSec :: TimeOfDay -> Double),+      lit' "TimeOfDay.midnight" Time.midnight,+      lit' "TimeOfDay.midday" Time.midday,+      lit'+        "TimeOfDay.makeTimeOfDayValid"+        \h m (s :: Double) -> Time.makeTimeOfDayValid h m (realToFrac s),+      lit' "TimeOfDay.timeOfDayToTime" (realToFrac . Time.timeOfDayToTime :: TimeOfDay -> Double),+      -- Text operations+      lit' "Text.decodeUtf8" Text.decodeUtf8,+      lit' "Text.encodeUtf8" Text.encodeUtf8,+      lit' "Text.eq" ((==) @Text),+      lit' "Text.length" Text.length,+      lit' "Text.concat" Text.concat,+      lit' "Text.breakOn" Text.breakOn,+      lit' "Text.lines" Text.lines,+      lit' "Text.words" Text.words,+      lit' "Text.unlines" Text.unlines,+      lit' "Text.unwords" Text.unwords,+      lit' "Text.intercalate" Text.intercalate,+      lit' "Text.reverse" Text.reverse,+      lit' "Text.toLower" Text.toLower,+      lit' "Text.toUpper" Text.toUpper,+      -- Needs Char operations.+      -- ("Text.any", lit' Text.any),+      -- ("Text.all", lit' Text.all),+      -- ("Text.filter", lit' Text.filter),+      lit' "Text.take" Text.take,+      lit' "Text.splitOn" Text.splitOn,+      lit' "Text.takeEnd" Text.takeEnd,+      lit' "Text.drop" Text.drop,+      lit' "Text.stripPrefix" Text.stripPrefix,+      lit' "Text.stripSuffix" Text.stripSuffix,+      lit' "Text.isSuffixOf" Text.isSuffixOf,+      lit' "Text.isPrefixOf" Text.isPrefixOf,+      lit' "Text.dropEnd" Text.dropEnd,+      lit' "Text.strip" Text.strip,+      lit' "Text.replace" Text.replace,+      lit' "Text.isPrefixOf" Text.isPrefixOf,+      lit' "Text.isSuffixOf" Text.isSuffixOf,+      lit' "Text.isInfixOf" Text.isInfixOf,+      lit' "Text.interact" (\f -> ByteString.interact (Text.encodeUtf8 . f . Text.decodeUtf8)),+      -- Int operations+      lit' "Int.readMaybe" (Read.readMaybe @Int . Text.unpack),+      lit' "Int.show" (Text.pack . show @Int),+      lit' "Int.eq" ((==) @Int),+      lit' "Int.plus" ((+) @Int),+      lit' "Int.mult" ((*) @Int),+      lit' "Int.subtract" (subtract @Int),+      lit' "Int.fromInteger" (fromInteger :: Integer -> Int),+      lit' "Int.toInteger" (toInteger :: Int -> Integer),+      -- Integer operations+      lit' "Integer.readMaybe" (Read.readMaybe @Integer . Text.unpack),+      lit' "Integer.plus" ((+) @Integer),+      lit' "Integer.mult" ((*) @Integer),+      lit' "Integer.subtract" (subtract @Integer),+      -- Double operations+      lit' "Double.readMaybe" (Read.readMaybe @Double . Text.unpack),+      lit' "Double.fromInt" (fromIntegral :: Int -> Double),+      lit' "Double.show" (Text.pack . show @Double),+      lit' "Double.showEFloat" (showsHelper showEFloat),+      lit' "Double.showFFloat" (showsHelper showFFloat),+      lit' "Double.eq" ((==) @Double),+      lit' "Double.plus" ((+) @Double),+      lit' "Double.mult" ((*) @Double),+      lit' "Double.subtract" (subtract @Double),+      -- Bytes I/O+      lit' "ByteString.hGet" ByteString.hGet,+      lit' "ByteString.hPutStr" ByteString.hPutStr,+      lit' "ByteString.writeFile" bytestring_writeFile,+      lit' "ByteString.readFile" bytestring_readFile,+      lit' "ByteString.readProcess" b_readProcess,+      lit' "ByteString.readProcess_" b_readProcess_,+      lit' "ByteString.readProcessStdout_" b_readProcessStdout_,+      lit' "ByteString.interact" ByteString.interact,+      lit' "ByteString.getContents" ByteString.getContents,+      -- Handles, buffering+      lit' "IO.stdout" IO.stdout,+      lit' "IO.stderr" IO.stderr,+      lit' "IO.stdin" IO.stdin,+      lit' "IO.hSetBuffering" IO.hSetBuffering,+      lit' "IO.NoBuffering" IO.NoBuffering,+      lit' "IO.LineBuffering" IO.LineBuffering,+      lit' "IO.BlockBuffering" IO.BlockBuffering,+      lit' "IO.hClose" IO.hClose,+      lit' "IO.openFile" (\f m -> IO.openFile (Text.unpack f) m),+      lit' "IO.ReadMode" IO.ReadMode,+      lit' "IO.WriteMode" IO.WriteMode,+      lit' "IO.AppendMode" IO.AppendMode,+      lit' "IO.ReadWriteMode" IO.ReadWriteMode,+      -- Concurrent stuff+      lit' "Concurrent.threadDelay" Concurrent.threadDelay,+      -- Bool+      lit' "Bool.True" Bool.True,+      lit' "Bool.False" Bool.False,+      lit' "Bool.not" Bool.not,+      -- Get arguments+      lit' "Environment.getArgs" $ fmap (map Text.pack) getArgs,+      lit' "Environment.getEnvironment" $ fmap (map (bimap Text.pack Text.pack)) getEnvironment,+      lit' "Environment.getEnv" $ fmap Text.pack . getEnv . Text.unpack,+      -- Current directory+      lit' "Directory.createDirectoryIfMissing" (\b f -> Dir.createDirectoryIfMissing b (Text.unpack f)),+      lit' "Directory.createDirectory" (Dir.createDirectory . Text.unpack),+      lit' "Directory.getCurrentDirectory" (fmap Text.pack Dir.getCurrentDirectory),+      lit' "Directory.listDirectory" (fmap (fmap Text.pack) . Dir.listDirectory . Text.unpack),+      lit' "Directory.setCurrentDirectory" (Dir.setCurrentDirectory . Text.unpack),+      lit' "Directory.renameFile" (\x y -> Dir.renameFile (Text.unpack x) (Text.unpack y)),+      lit' "Directory.copyFile" (\x y -> Dir.copyFile (Text.unpack x) (Text.unpack y)),+      lit' "Directory.removeFile" (\x -> Dir.removeFile (Text.unpack x)),+      lit' "Directory.doesFileExist" (\x -> Dir.doesFileExist (Text.unpack x)),+      lit' "Directory.doesDirectoryExist" (\x -> Dir.doesDirectoryExist (Text.unpack x)),+      -- Process+      lit' "Process.proc" $ \n xs -> proc (Text.unpack n) (map Text.unpack xs),+      lit' "Process.setEnv" $ Process.setEnv @() @() @() . map (bimap Text.unpack Text.unpack),+      -- Exit+      lit' "Exit.ExitSuccess" Exit.ExitSuccess,+      lit' "Exit.ExitFailure" Exit.ExitFailure,+      -- Lists+      lit' "List.and" (List.and @[]),+      lit' "List.or" (List.or @[]),+      -- Json+      lit' "Json.decode" (Json.decode . L.fromStrict :: ByteString -> Maybe Value),+      lit' "Json.encode" (L.toStrict . Json.encode :: Value -> ByteString),+      lit' "Json.Number" (Json.toJSON :: Double -> Value),+      lit' "Json.String" (Json.toJSON :: Text -> Value),+      lit' "Json.Bool" (Json.toJSON :: Bool -> Value),+      lit' "Json.Null" Json.Null,+      lit' "Json.Array" (Json.toJSON :: Vector Value -> Value),+      lit' "Json.Object" (Json.toJSON :: Map Text Value -> Value),+      -- Records+      lit' "hell:Hell.NilR" NilR,+      -- Nullary+      lit' "hell:Hell.Nullary" Nullary,+      -- Options+      lit' "Options.switch" Options.switch,+      lit' "Options.strOption" (Options.strOption @Text),+      lit' "Options.strArgument" (Options.strArgument @Text)+    ]+  where+    lit' :: forall a. (Type.Typeable a) => String -> a -> (String, (UTerm (), SomeTypeRep))+    lit' str x = (str, (lit (NameP str) x, SomeTypeRep $ Type.typeOf x))++    showsHelper ::+      (Maybe Int -> Double -> (String -> String)) ->+      (Maybe Int -> Double -> (Text -> Text))+    showsHelper f = \mi a ->+      \text -> Text.pack $ (f mi a) (Text.unpack text)++--------------------------------------------------------------------------------+-- Derive prims TH++-- Polymorphic literals are derived here.+--+-- In order to keep the whole language in one file, this ends up being+-- a big TH block. So I introduce explicit layout immediately, that+-- lets me put all the related components for TH generation inside+-- here and stay readable.+polyLits :: Map String (Forall, [TH.Uniq], IRep TH.Uniq, TH.Type)+polyLits =+  $( let -- Top-level expression generated by this TH declaration.+         toplevel :: Q TH.Exp+         toplevel = do+           let generated = do+                 prims <- primsParsed+                 TH.listE $+                   flip+                     map+                     prims+                     \(name, expr, typeForDocs, tyVarBndrs, ctx, qualifiedType) ->+                       let constraints = toList $ Set.fromList $ map getConstraint ctx+                           forall' =+                             foldr+                               stepBinder+                               (foldr stepConstraint (term name expr qualifiedType tyVarBndrs) constraints)+                               tyVarBndrs+                           uniques =+                             TH.listE $+                               map+                                 (TH.litE . TH.integerL . nameUnique . fst . tyVarBndrNameKind)+                                 tyVarBndrs+                           irep = typeToIRep qualifiedType+                        in [|((name, ($forall', $uniques, $irep, typeForDocs)))|]+           [|Map.fromList $generated|]++         -- By default, the term is whatever is in the expression. For record+         -- accessors (get/set/modify), I magically generate one at+         -- compile-time on-demand.+         term :: String -> TH.Exp -> TH.Type -> [TH.TyVarBndr TH.Specificity] -> Q TH.Exp+         term op _ qualifiedType tyVarBndrs+           | Just cons <- List.lookup op recordOperators =+               let vars =+                     [ TH.varT (normalizeName name)+                       | v <- tyVarBndrs,+                         let (name, _k) = tyVarBndrNameKind v+                     ]+                in [|+                     $cons+                       (TypeRep @($(vars !! 0)))+                       (TypeRep @($(vars !! 1)))+                       (TypeRep @($(vars !! 2)))+                       (TypeRep @($(vars !! 3)))+                       \f ->+                         Term $ typed (f :: $((pure $ normalizeType qualifiedType)))+                     |]+         term _ expr qualifiedType _ =+           [|Term $ typed $(TH.sigE (pure expr) (pure $ normalizeType qualifiedType))|]++         -- \| Magic record operators.+         recordOperators :: [(String, Q TH.Exp)]+         recordOperators =+           [ ("Record.get", [|GetOf|]),+             ("Record.set", [|SetOf|]),+             ("Record.modify", [|ModifyOf|])+           ]++         -- Single step in the class decorating (Klass a => ..) right-fold.+         stepConstraint :: (TH.Name, TH.Name) -> Q TH.Exp -> Q TH.Exp+         stepConstraint (className, tyVarName0) expr =+           [|+             ClassConstraint+               $nameE+               $typeRepE+               $expr+             |]+           where+             name = normalizeName tyVarName0+             nameE = TH.varE name+             typeRepE = [|(TypeRep @($(TH.conT className)))|]++         -- Single step in the variable-binding (forall x. ..) right-fold.+         stepBinder :: TH.TyVarBndr TH.Specificity -> Q TH.Exp -> Q TH.Exp+         stepBinder tyVarBndr expr =+           [|+             Forall $typeRepE \($nameP :: TypeRep $nameT) ->+               case $nameE of+                 TypeRep -> $expr+             |]+           where+             (name0, kind) = tyVarBndrNameKind tyVarBndr+             name = normalizeName name0+             nameE = TH.varE name+             nameP = TH.varP name+             nameT = TH.varT name+             typeRepE = [|TypeRep @($(pure kind))|]++         normalizeType :: TH.Type -> TH.Type+         normalizeType = SYB.everywhere $ SYB.mkT \case+           TH.VarT n -> TH.VarT $ normalizeName n+           t -> t++         normalizeName :: TH.Name -> TH.Name+         normalizeName name = TH.mkName $ 'n' : (show $ nameUnique name)++         -- Parse the prims out of primsExpr.+         primsParsed :: Q [(String, TH.Exp, TH.Type, [TH.TyVarBndr TH.Specificity], TH.Cxt, TH.Type)]+         primsParsed = do+           expr <- primsExpr+           let binds = expBinds expr+            in pure $ map parsePrim binds++         -- Convert a TH type to our internal IRep type.+         typeToIRep :: TH.Type -> Q TH.Exp+         typeToIRep =+           ( \case+               TH.AppT (TH.AppT TH.ArrowT f) x -> [|IFun $(typeToIRep f) $(typeToIRep x)|]+               TH.AppT f x -> [|IApp $(typeToIRep f) $(typeToIRep x)|]+               TH.ConT name ->+                 [|ICon (SomeTypeRep $(TH.appTypeE (TH.varE 'typeRep) (TH.conT name)))|]+               TH.VarT a -> [|IVar $(TH.litE $ TH.IntegerL $ nameUnique a)|]+               TH.ListT -> [|ICon (SomeTypeRep (typeRep @[]))|]+               TH.TupleT 2 -> [|ICon (SomeTypeRep (typeRep @(,)))|]+               TH.TupleT 3 -> [|ICon (SomeTypeRep (typeRep @(,,)))|]+               TH.TupleT 4 -> [|ICon (SomeTypeRep (typeRep @(,,,)))|]+               TH.TupleT 0 -> [|ICon (SomeTypeRep (typeRep @()))|]+               ty0@TH.PromotedT {} ->+                 [|ICon (SomeTypeRep $(TH.appTypeE (TH.varE 'typeRep) (pure ty0)))|]+               t -> error $ "Unexpected type shape: " ++ show t+           )++         -- Get the unique integer for a name; hard errors if not available.+         nameUnique :: TH.Name -> Integer+         nameUnique (TH.Name _ (TH.NameU i)) = i+         nameUnique name = error $ "Bad TH problem in nameUnique: " ++ show name++         -- Get statements from the do-notation; hard errors otherwise.+         expBinds :: TH.Exp -> [TH.Stmt]+         expBinds (TH.DoE Nothing binds) = binds+         expBinds e = error $ "Expected plain do-notation, but got: " ++ show e++         -- Get a very simple, unary constraint: Klass tyvar+         getConstraint :: TH.Type -> (TH.Name, TH.Name)+         getConstraint (TH.AppT (TH.ConT cls') (TH.VarT v)) = (cls', v)+         getConstraint cons = error $ "Unsupported class constraint shape: " ++ show cons++         -- \| Parse out a primitive's name, expression and type.+         --+         -- Example:+         --+         --   "Function.id" Function.id :: forall a. a -> a+         parsePrim ::+           TH.Stmt ->+           (String, TH.Exp, TH.Type, [TH.TyVarBndr TH.Specificity], TH.Cxt, TH.Type)+         parsePrim+           ( TH.NoBindS+               ( TH.SigE+                   (TH.AppE (TH.LitE (TH.StringL string)) expr0)+                   thtype@(TH.ForallT vars constraints typ)+                 )+             ) =+             (string, expr0, thtype, vars, constraints, typ)+         parsePrim e =+           error $+             "Should be of the form \"Some.name\" The.name :: T\ngot: "+               ++ show e++         -- Get the name of the type variable, must be specified, not+         -- inferred. Kind assumed to be * unless specified.+         tyVarBndrNameKind :: TH.TyVarBndr TH.Specificity -> (TH.Name, TH.Kind)+         tyVarBndrNameKind = \case+           (TH.PlainTV v TH.SpecifiedSpec) -> (v, TH.StarT)+           (TH.KindedTV v TH.SpecifiedSpec k) -> (v, k)+           _ -> error "The type variable specificity should not be inferred."++         -- Where all primitives are defined. Consists of the name, expression+         -- and type. Unless stated otherwise, all type variables are assumed+         -- to be of kind Type.+         primsExpr :: Q TH.Exp+         primsExpr =+           [|+             do+               -- Records+               "hell:Hell.ConsR" ConsR :: forall (k :: Symbol) a (xs :: List). SSymbol k -> a -> Record xs -> Record (ConsL k a xs)+               "Record.get" _ :: forall (k :: Symbol) a (t :: Symbol) (xs :: List). Tagged t (Record xs) -> a+               "Record.set" _ :: forall (k :: Symbol) a (t :: Symbol) (xs :: List). a -> Tagged t (Record xs) -> Tagged t (Record xs)+               "Record.modify" _ :: forall (k :: Symbol) a (t :: Symbol) (xs :: List). (a -> a) -> Tagged t (Record xs) -> Tagged t (Record xs)++               -- Variants+               "hell:Hell.LeftV" LeftV :: forall (k :: Symbol) a (xs :: List). SSymbol k -> a -> Variant (ConsL k a xs)+               "hell:Hell.RightV" RightV :: forall (k :: Symbol) a (xs :: List) (k'' :: Symbol) a''. Variant (ConsL k'' a'' xs) -> Variant (ConsL k a (ConsL k'' a'' xs))+               "hell:Hell.NilA" NilA :: forall r. Accessor 'NilL r+               "hell:Hell.WildA" WildA :: forall r (xs :: List). r -> Accessor xs r+               "hell:Hell.ConsA" ConsA :: forall (k :: Symbol) a r (xs :: List). (a -> r) -> Accessor xs r -> Accessor (ConsL k a xs) r+               "hell:Hell.runAccessor" runAccessor :: forall (t :: Symbol) r (xs :: List). Tagged t (Variant xs) -> Accessor xs r -> r++               -- Tagged+               "hell:Hell.Tagged" Tagged :: forall (t :: Symbol) a. SSymbol t -> a -> Tagged t a++               -- Functor+               "Functor.fmap" fmap :: forall (f :: Type -> Type) a b. (Functor f) => (a -> b) -> f a -> f b++               -- Operators+               "$" (Function.$) :: forall a b. (a -> b) -> a -> b+               "." (Function..) :: forall a b c. (b -> c) -> (a -> b) -> a -> c+               "<>" (<>) :: forall m. (Semigroup m) => m -> m -> m++               -- Monad+               "Monad.bind" (Prelude.>>=) :: forall (m :: Type -> Type) a b. (Monad m) => m a -> (a -> m b) -> m b+               "Monad.then" (Prelude.>>) :: forall (m :: Type -> Type) a b. (Monad m) => m a -> m b -> m b+               "Monad.return" return :: forall a (m :: Type -> Type). (Monad m) => a -> m a++               -- Applicative operations+               "Applicative.pure" pure :: forall (f :: Type -> Type) a. (Applicative f) => a -> f a+               "<*>" (<*>) :: forall (f :: Type -> Type) a b. (Applicative f) => f (a -> b) -> f a -> f b+               "<$>" (<$>) :: forall (f :: Type -> Type) a b. (Functor f) => (a -> b) -> f a -> f b+               "<**>" (Options.<**>) :: forall (f :: Type -> Type) a b. (Applicative f) => f a -> f (a -> b) -> f b++               -- Alternative operations+               "Alternative.optional" (optional) :: forall (f :: Type -> Type) a. (Alternative f) => f a -> f (Maybe a)++               -- Monadic operations+               "Monad.mapM_" mapM_ :: forall a (m :: Type -> Type). (Monad m) => (a -> m ()) -> [a] -> m ()+               "Monad.forM_" forM_ :: forall a (m :: Type -> Type). (Monad m) => [a] -> (a -> m ()) -> m ()+               "Monad.mapM" mapM :: forall a b (m :: Type -> Type). (Monad m) => (a -> m b) -> [a] -> m [b]+               "Monad.forM" forM :: forall a b (m :: Type -> Type). (Monad m) => [a] -> (a -> m b) -> m [b]+               "Monad.sequence" sequence :: forall a (m :: Type -> Type). (Monad m) => [m a] -> m [a]+               "Monad.when" when :: forall (m :: Type -> Type). (Monad m) => Bool -> m () -> m ()++               -- IO+               "IO.mapM_" mapM_ :: forall a. (a -> IO ()) -> [a] -> IO ()+               "IO.forM_" forM_ :: forall a. [a] -> (a -> IO ()) -> IO ()+               "IO.pure" pure :: forall a. a -> IO a+               "IO.print" (t_putStrLn . Text.pack . Show.show) :: forall a. (Show a) => a -> IO ()+               "Timeout.timeout" Timeout.timeout :: forall a. Int -> IO a -> IO (Maybe a)++               -- Show+               "Show.show" (Text.pack . Show.show) :: forall a. (Show a) => a -> Text++               -- Eq/Ord+               "Eq.eq" (Eq.==) :: forall a. (Eq a) => a -> a -> Bool+               "Ord.lt" (Ord.<) :: forall a. (Ord a) => a -> a -> Bool+               "Ord.gt" (Ord.>) :: forall a. (Ord a) => a -> a -> Bool++               -- Tuples+               "Tuple.(,)" (,) :: forall a b. a -> b -> (a, b)+               "Tuple.(,)" (,) :: forall a b. a -> b -> (a, b)+               "Tuple.(,,)" (,,) :: forall a b c. a -> b -> c -> (a, b, c)+               "Tuple.(,,,)" (,,,) :: forall a b c d. a -> b -> c -> d -> (a, b, c, d)++               -- Exit+               "Exit.die" (Exit.die . Text.unpack) :: forall a. Text -> IO a+               "Exit.exitWith" Exit.exitWith :: forall a. ExitCode -> IO a+               "Exit.exitCode" exit_exitCode :: forall a. a -> (Int -> a) -> ExitCode -> a++               -- Exceptions+               "Error.error" (error . Text.unpack) :: forall a. Text -> a++               -- Bool+               "Bool.bool" Bool.bool :: forall a. a -> a -> Bool -> a++               -- Function+               "Function.id" Function.id :: forall a. a -> a+               "Function.fix" Function.fix :: forall a. (a -> a) -> a++               -- Set+               "Set.fromList" Set.fromList :: forall a. (Ord a) => [a] -> Set a+               "Set.insert" Set.insert :: forall a. (Ord a) => a -> Set a -> Set a+               "Set.member" Set.member :: forall a. (Ord a) => a -> Set a -> Bool+               "Set.delete" Set.delete :: forall a. (Ord a) => a -> Set a -> Set a+               "Set.union" Set.union :: forall a. (Ord a) => Set a -> Set a -> Set a+               "Set.difference" Set.difference :: forall a. (Ord a) => Set a -> Set a -> Set a+               "Set.intersection" Set.intersection :: forall a. (Ord a) => Set a -> Set a -> Set a+               "Set.toList" Set.toList :: forall a. Set a -> [a]+               "Set.size" Set.size :: forall a. Set a -> Int+               "Set.singleton" Set.singleton :: forall a. (Ord a) => a -> Set a++               -- These+               "These.This" These.This :: forall a b. a -> These a b+               "These.That" These.That :: forall a b. b -> These a b+               "These.These" These.These :: forall a b. a -> b -> These a b+               "These.these" These.these :: forall a b c. (a -> c) -> (b -> c) -> (a -> b -> c) -> These a b -> c++               -- Trees+               "Tree.Node" Tree.Node :: forall a. a -> [Tree a] -> Tree a+               "Tree.unfoldTree" Tree.unfoldTree :: forall a b. (b -> (a, [b])) -> b -> Tree a+               "Tree.foldTree" Tree.foldTree :: forall a b. (a -> [b] -> b) -> Tree a -> b+               "Tree.flatten" Tree.flatten :: forall a. Tree a -> [a]+               "Tree.levels" Tree.levels :: forall a. Tree a -> [[a]]+               "Tree.map" fmap :: forall a b. (a -> b) -> Tree a -> Tree b++               -- Lists+               "List.cons" (:) :: forall a. a -> [a] -> [a]+               "List.nil" [] :: forall a. [a]+               "List.length" List.length :: forall a. [a] -> Int+               "List.scanl'" List.scanl' :: forall a b. (b -> a -> b) -> b -> [a] -> [b]+               "List.scanr" List.scanr :: forall a b. (a -> b -> b) -> b -> [a] -> [b]+               "List.concat" List.concat :: forall a. [[a]] -> [a]+               "List.concatMap" List.concatMap :: forall a b. (a -> [b]) -> [a] -> [b]+               "List.drop" List.drop :: forall a. Int -> [a] -> [a]+               "List.take" List.take :: forall a. Int -> [a] -> [a]+               "List.splitAt" List.splitAt :: forall a. Int -> [a] -> ([a], [a])+               "List.break" List.break :: forall a. (a -> Bool) -> [a] -> ([a], [a])+               "List.span" List.span :: forall a. (a -> Bool) -> [a] -> ([a], [a])+               "List.partition" List.partition :: forall a. (a -> Bool) -> [a] -> ([a], [a])+               "List.takeWhile" List.takeWhile :: forall a. (a -> Bool) -> [a] -> [a]+               "List.dropWhile" List.dropWhile :: forall a. (a -> Bool) -> [a] -> [a]+               "List.dropWhileEnd" List.dropWhileEnd :: forall a. (a -> Bool) -> [a] -> [a]+               "List.map" List.map :: forall a b. (a -> b) -> [a] -> [b]+               "List.any" List.any :: forall a. (a -> Bool) -> [a] -> Bool+               "List.all" List.all :: forall a. (a -> Bool) -> [a] -> Bool+               "List.iterate'" List.iterate' :: forall a. (a -> a) -> a -> [a]+               "List.repeat" List.repeat :: forall a. a -> [a]+               "List.cycle" List.cycle :: forall a. [a] -> [a]+               "List.filter" List.filter :: forall a. (a -> Bool) -> [a] -> [a]+               "List.foldl'" List.foldl' :: forall a b. (b -> a -> b) -> b -> [a] -> b+               "List.foldr" List.foldr :: forall a b. (a -> b -> b) -> b -> [a] -> b+               "List.unfoldr" List.unfoldr :: forall a b. (b -> Maybe (a, b)) -> b -> [a]+               "List.zip" List.zip :: forall a b. [a] -> [b] -> [(a, b)]+               "List.mapAccumL" List.mapAccumL :: forall s a b. (s -> a -> (s, b)) -> s -> [a] -> (s, [b])+               "List.mapAccumR" List.mapAccumL :: forall s a b. (s -> a -> (s, b)) -> s -> [a] -> (s, [b])+               "List.zipWith" List.zipWith :: forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]+               "List.lookup" List.lookup :: forall a b. (Eq a) => a -> [(a, b)] -> Maybe b+               "List.find" List.find :: forall a. (a -> Bool) -> [a] -> Maybe a+               "List.sort" List.sort :: forall a. (Ord a) => [a] -> [a]+               "List.group" List.group :: forall a. (Eq a) => [a] -> [[a]]+               "List.isPrefixOf" List.isPrefixOf :: forall a. (Eq a) => [a] -> [a] -> Bool+               "List.isSuffixOf" List.isSuffixOf :: forall a. (Eq a) => [a] -> [a] -> Bool+               "List.isInfixOf" List.isInfixOf :: forall a. (Eq a) => [a] -> [a] -> Bool+               "List.isSubsequenceOf" List.isSubsequenceOf :: forall a. (Eq a) => [a] -> [a] -> Bool+               "List.groupBy" List.groupBy :: forall a. (a -> a -> Bool) -> [a] -> [[a]]+               "List.reverse" List.reverse :: forall a. [a] -> [a]+               "List.nubOrd" nubOrd :: forall a. (Ord a) => [a] -> [a]+               "List.inits" List.inits :: forall a. [a] -> [[a]]+               "List.tails" List.tails :: forall a. [a] -> [[a]]+               "List.deleteBy" List.deleteBy :: forall a. (a -> a -> Bool) -> a -> [a] -> [a]+               "List.elem" List.elem :: forall a. (Eq a) => a -> [a] -> Bool+               "List.notElem" List.notElem :: forall a. (Eq a) => a -> [a] -> Bool+               "List.sortOn" List.sortOn :: forall a b. (Ord b) => (a -> b) -> [a] -> [a]+               "List.null" List.null :: forall a. [a] -> Bool+               "List.elemIndex" List.elemIndex :: forall a. (Eq a) => a -> [a] -> Maybe Int+               "List.elemIndices" List.elemIndices :: forall a. (Eq a) => a -> [a] -> [Int]+               "List.findIndex" List.findIndex :: forall a. (a -> Bool) -> [a] -> Maybe Int+               "List.findIndices" List.findIndices :: forall a. (a -> Bool) -> [a] -> [Int]+               "List.uncons" List.uncons :: forall a. [a] -> Maybe (a, [a])+               "List.intersperse" List.intersperse :: forall a. a -> [a] -> [a]+               "List.intercalate" List.intercalate :: forall a. [a] -> [[a]] -> [a]+               "List.transpose" List.transpose :: forall a. [[a]] -> [[a]]+               "List.subsequences" List.subsequences :: forall a. [a] -> [[a]]+               "List.permutations" List.permutations :: forall a. [a] -> [[a]]++               -- Vector+               "Vector.fromList" Vector.fromList :: forall a. [a] -> Vector a+               "Vector.toList" Vector.toList :: forall a. Vector a -> [a]++               -- Map+               "Map.fromList" Map.fromList :: forall k a. (Ord k) => [(k, a)] -> Map k a+               "Map.lookup" Map.lookup :: forall k a. (Ord k) => k -> Map k a -> Maybe a+               "Map.insert" Map.insert :: forall k a. (Ord k) => k -> a -> Map k a -> Map k a+               "Map.delete" Map.delete :: forall k a. (Ord k) => k -> Map k a -> Map k a+               "Map.singleton" Map.singleton :: forall k a. (Ord k) => k -> a -> Map k a+               "Map.size" Map.size :: forall k a. Map k a -> Int+               "Map.filter" Map.filter :: forall k a. (a -> Bool) -> Map k a -> Map k a+               "Map.filterWithKey" Map.filterWithKey :: forall k a. (k -> a -> Bool) -> Map k a -> Map k a+               "Map.any" any :: forall k a. (a -> Bool) -> Map k a -> Bool+               "Map.all" all :: forall k a. (a -> Bool) -> Map k a -> Bool+               "Map.insertWith" Map.insertWith :: forall k a. (Ord k) => (a -> a -> a) -> k -> a -> Map k a -> Map k a+               "Map.adjust" Map.adjust :: forall k a. (Ord k) => (a -> a) -> k -> Map k a -> Map k a+               "Map.unionWith" Map.unionWith :: forall k a. (Ord k) => (a -> a -> a) -> Map k a -> Map k a -> Map k a+               "Map.map" Map.map :: forall a b k. (a -> b) -> Map k a -> Map k b+               "Map.toList" Map.toList :: forall k a. Map k a -> [(k, a)]+               "Map.keys" Map.keys :: forall k a. Map k a -> [k]+               "Map.elems" Map.elems :: forall k a. Map k a -> [a]++               -- Maybe+               "Maybe.maybe" Maybe.maybe :: forall a b. b -> (a -> b) -> Maybe a -> b+               "Maybe.Nothing" Maybe.Nothing :: forall a. Maybe a+               "Maybe.Just" Maybe.Just :: forall a. a -> Maybe a+               "Maybe.listToMaybe" Maybe.listToMaybe :: forall a. [a] -> Maybe a+               "Maybe.mapMaybe" Maybe.mapMaybe :: forall a b. (a -> Maybe b) -> [a] -> [b]++               -- Either+               "Either.either" Either.either :: forall a b x. (a -> x) -> (b -> x) -> Either a b -> x+               "Either.Left" Either.Left :: forall a b. a -> Either a b+               "Either.Right" Either.Right :: forall a b. b -> Either a b++               -- Async+               "Async.concurrently" Async.concurrently :: forall a b. IO a -> IO b -> IO (a, b)+               "Async.race" Async.race :: forall a b. IO a -> IO b -> IO (Either a b)+               "Async.pooledMapConcurrently_" Async.pooledMapConcurrently_ :: forall a. (a -> IO ()) -> [a] -> IO ()+               "Async.pooledForConcurrently_" Async.pooledForConcurrently_ :: forall a. [a] -> (a -> IO ()) -> IO ()+               "Async.pooledMapConcurrently" Async.pooledMapConcurrently :: forall a b. (a -> IO b) -> [a] -> IO [b]+               "Async.pooledForConcurrently" Async.pooledForConcurrently :: forall a b. [a] -> (a -> IO b) -> IO [b]++               -- JSON+               "Json.value" json_value :: forall a. a -> (Bool -> a) -> (Text -> a) -> (Double -> a) -> (Vector Value -> a) -> (Map Text Value -> a) -> Value -> a++               -- Temp+               "Temp.withSystemTempFile" temp_withSystemTempFile :: forall a. Text -> (Text -> IO.Handle -> IO a) -> IO a+               "Temp.withSystemTempDirectory" temp_withSystemTempDirectory :: forall a. Text -> (Text -> IO a) -> IO a++               -- Process+               "Process.runProcess" runProcess :: forall a b c. ProcessConfig a b c -> IO ExitCode+               "Process.runProcess_" runProcess_ :: forall a b c. ProcessConfig a b c -> IO ()+               "Process.setStdin" setStdin :: forall stdin stdin' stdout stderr. StreamSpec 'STInput stdin' -> ProcessConfig stdin stdout stderr -> ProcessConfig stdin' stdout stderr+               "Process.setStdout" setStdout :: forall stdin stdout stdout' stderr. StreamSpec 'STOutput stdout' -> ProcessConfig stdin stdout stderr -> ProcessConfig stdin stdout' stderr+               "Process.setStderr" setStderr :: forall stdin stdout stderr stderr'. StreamSpec 'STOutput stderr' -> ProcessConfig stdin stdout stderr -> ProcessConfig stdin stdout stderr'+               "Process.nullStream" Process.nullStream :: forall (a :: StreamType). StreamSpec a ()+               "Process.useHandleClose" useHandleClose :: forall (a :: StreamType). IO.Handle -> StreamSpec a ()+               "Process.useHandleOpen" useHandleOpen :: forall (a :: StreamType). IO.Handle -> StreamSpec a ()+               "Process.setWorkingDir" process_setWorkingDir :: forall a b c. Text -> ProcessConfig a b c -> ProcessConfig a b c++               -- Options+               "Options.execParser" Options.execParser :: forall a. Options.ParserInfo a -> IO a+               "Options.info" Options.info :: forall a. Options.Parser a -> Options.InfoMod a -> Options.ParserInfo a+               "Options.helper" Options.helper :: forall a. Options.Parser (a -> a)+               "Options.fullDesc" Options.fullDesc :: forall a. Options.InfoMod a+               "Options.flag" Options.flag :: forall a. a -> a -> Options.Mod Options.FlagFields a -> Parser a+               "Options.flag'" Options.flag' :: forall a. a -> Options.Mod Options.FlagFields a -> Parser a+               "Option.long" option_long :: forall a. Text -> Options.Mod Options.OptionFields a+               "Option.help" options_help :: forall a. Text -> Options.Mod Options.OptionFields a+               "Options.hsubparser" Options.hsubparser :: forall a. Options.Mod Options.CommandFields a -> Parser a+               "Options.command" options_command :: forall a. Text -> Options.ParserInfo a -> Options.Mod Options.CommandFields a+               "Flag.help" options_help :: forall a. Text -> Options.Mod Options.FlagFields a+               "Flag.long" flag_long :: forall a. Text -> Options.Mod Options.FlagFields a+               "Option.value" option_value :: forall a. a -> Options.Mod Options.OptionFields a+               "Argument.value" argument_value :: forall a. a -> Options.Mod Options.ArgumentFields a+               "Argument.metavar" argument_metavar :: forall a. Text -> Options.Mod Options.ArgumentFields a+               "Argument.help" options_help :: forall a. Text -> Options.Mod Options.ArgumentFields a+               "Options.progDesc" options_progDesc :: forall a. Text -> Options.InfoMod a+               "Options.header" options_header :: forall a. Text -> Options.InfoMod a+             |]+      in toplevel+   )++--------------------------------------------------------------------------------+-- Primitive sum types (for case support)++-- Easy access lookup for case alt desugaring.+primitiveConstructors :: Map String (String, Int)+--                           ^ cons ^ type   ^ arity+primitiveConstructors = Map.fromList [+  (cons, (typ, arity))+  | (typ,conses) <- primitiveSumTypes+  , (cons,arity) <- conses+  ]++-- | Easier-to-maintain list for me, the author.+primitiveSumTypes :: [ (String, [(String,     Int)]) ]+--                     ^ type    ^ cons   ^ arity+primitiveSumTypes =+  [ ("Maybe.maybe",[("Maybe.Nothing",0),("Maybe.Just",1)]),+    ("Either.either", [("Either.Left", 1),("Either.Right", 1)]),+    ("Exit.exitCode", [("Exit.ExitSuccess", 0),("Exit.ExitFailure", 1)]),+    ("Bool.bool", [("Bool.False", 0),("Bool.True", 0)]),+    ("These.these", [("These.This", 1),("These.That", 1),("These.These",2)]),+    ("Json.value", [("Json.Null",0),("Json.Bool",1),("Json.String",1),("Json.Number",1),("Json.Array", 1),("Json.Object", 1)])+  ]+++--------------------------------------------------------------------------------+-- Internal-use only, used by the desugarer++argument_metavar :: forall a. Text -> Options.Mod Options.ArgumentFields a+argument_metavar = Options.metavar . Text.unpack++option_value :: forall a. a -> Options.Mod Options.OptionFields a+option_value = Options.value++options_progDesc :: forall a. Text -> Options.InfoMod a+options_progDesc = Options.progDesc . Text.unpack++options_header :: forall a. Text -> Options.InfoMod a+options_header = Options.header . Text.unpack++argument_value :: forall a. a -> Options.Mod Options.ArgumentFields a+argument_value = Options.value++options_help :: forall f a. Text -> Options.Mod f a+options_help = Options.help . Text.unpack++options_command :: forall a. Text -> Options.ParserInfo a -> Options.Mod Options.CommandFields a+options_command = Options.command . Text.unpack++option_long :: forall a. Text -> Options.Mod Options.OptionFields a+option_long = Options.long . Text.unpack++flag_long :: forall a. Text -> Options.Mod Options.FlagFields a+flag_long = Options.long . Text.unpack++cons' :: HSE.SrcSpanInfo -> UTerm ()+cons' = unsafeGetForall "List.cons"++nil' :: HSE.SrcSpanInfo -> UTerm ()+nil' = unsafeGetForall "List.nil"++bool' :: HSE.SrcSpanInfo -> UTerm ()+bool' = unsafeGetForall "Bool.bool"++tuple' :: Int -> HSE.SrcSpanInfo -> UTerm ()+tuple' 0 = unsafeGetForall "Tuple.()"+tuple' 2 = unsafeGetForall "Tuple.(,)"+tuple' 3 = unsafeGetForall "Tuple.(,,)"+tuple' 4 = unsafeGetForall "Tuple.(,,,)"+tuple' _ = error "Bad compile-time lookup for tuple'."++unsafeGetForall :: String -> HSE.SrcSpanInfo -> UTerm ()+unsafeGetForall key l = Maybe.fromMaybe (error $ "Bad compile-time lookup for " ++ key) $ do+  (forall', vars, irep, _) <- Map.lookup key polyLits+  pure (UForall (NameP key) l () [] forall' vars irep [])++--------------------------------------------------------------------------------+-- Hidden terms and types, implementation-detail, used by Hell++hellModule :: l -> HSE.ModuleName l+hellModule l = HSE.ModuleName l "hell:Hell"++hellQName :: l -> String -> HSE.QName l+hellQName l string = HSE.Qual l (hellModule l) (HSE.Ident l string)++hellTyCon :: l -> String -> HSE.Type l+hellTyCon l string = HSE.TyCon l $ hellQName l string++hellCon :: l -> String -> HSE.Exp l+hellCon l string = HSE.Con l $ hellQName l string++hellTaggedTyCon :: l -> HSE.Type l+hellTaggedTyCon l = hellTyCon l "Tagged"++hellRecordTyCon :: l -> HSE.Type l+hellRecordTyCon l = hellTyCon l "Record"++hellVariantTyCon :: l -> HSE.Type l+hellVariantTyCon l = hellTyCon l "Variant"++hellNilTyCon :: l -> HSE.Type l+hellNilTyCon l = hellTyCon l "NilL"++hellConsTyCon :: l -> HSE.Type l+hellConsTyCon l = hellTyCon l "ConsL"++hellTaggedCon :: l -> HSE.Exp l+hellTaggedCon l = hellCon l "Tagged"++hellSSymbolCon :: l -> HSE.Exp l+hellSSymbolCon l = hellCon l "SSymbol"++--------------------------------------------------------------------------------+-- Accessor for ExitCode++exit_exitCode :: a -> (Int -> a) -> ExitCode -> a+exit_exitCode ok fail' = \case+  ExitSuccess -> ok+  ExitFailure i -> fail' i++--------------------------------------------------------------------------------+-- UTF-8 specific operations without all the environment gubbins+--+-- Much better than what Data.Text.IO provides++bytestring_readFile :: Text -> IO ByteString+bytestring_readFile = ByteString.readFile . Text.unpack++bytestring_writeFile :: Text -> ByteString -> IO ()+bytestring_writeFile = ByteString.writeFile . Text.unpack++t_setStdin :: Text -> ProcessConfig () () () -> ProcessConfig () () ()+t_setStdin text = setStdin (byteStringInput (L.fromStrict (Text.encodeUtf8 text)))++t_readProcess :: ProcessConfig () () () -> IO (ExitCode, Text, Text)+t_readProcess c = do+  (code, out, err) <- b_readProcess c+  pure (code, Text.decodeUtf8 out, Text.decodeUtf8 err)++t_readProcess_ :: ProcessConfig () () () -> IO (Text, Text)+t_readProcess_ c = do+  (out, err) <- b_readProcess_ c+  pure (Text.decodeUtf8 out, Text.decodeUtf8 err)++t_readProcessStdout_ :: ProcessConfig () () () -> IO Text+t_readProcessStdout_ c = do+  out <- b_readProcessStdout_ c+  pure (Text.decodeUtf8 out)++t_putStrLn :: Text -> IO ()+t_putStrLn = ByteString.hPutBuilder IO.stdout . (<> "\n") . ByteString.byteString . Text.encodeUtf8++t_hPutStr :: IO.Handle -> Text -> IO ()+t_hPutStr h = ByteString.hPutBuilder h . ByteString.byteString . Text.encodeUtf8++t_putStr :: Text -> IO ()+t_putStr = t_hPutStr IO.stdout++t_getLine :: IO Text+t_getLine = fmap Text.decodeUtf8 S8.getLine++t_writeFile :: Text -> Text -> IO ()+t_writeFile fp t = ByteString.writeFile (Text.unpack fp) (Text.encodeUtf8 t)++t_appendFile :: Text -> Text -> IO ()+t_appendFile fp t = ByteString.appendFile (Text.unpack fp) (Text.encodeUtf8 t)++t_readFile :: Text -> IO Text+t_readFile fp = fmap Text.decodeUtf8 (ByteString.readFile (Text.unpack fp))++--------------------------------------------------------------------------------+-- JSON operations++-- Accessor for JSON.+json_value ::+  forall a.+  a -> -- Null+  (Bool -> a) -> -- Bool+  (Text -> a) -> -- String+  (Double -> a) -> -- Number+  (Vector Value -> a) -> -- Array+  (Map Text Value -> a) -> -- Object+  Value ->+  a+json_value null' bool string number array object =+  \case+    Json.Null -> null'+    Json.Bool s -> bool s+    Json.String s -> string s+    Json.Number s -> number (realToFrac s)+    Json.Array s -> array s+    Json.Object s -> object $ KeyMap.toMapText $ s++--------------------------------------------------------------------------------+-- ByteString operations++b_readProcess :: ProcessConfig () () () -> IO (ExitCode, ByteString, ByteString)+b_readProcess c = do+  (code, out, err) <- readProcess c+  pure (code, L.toStrict out, L.toStrict err)++b_readProcess_ :: ProcessConfig () () () -> IO (ByteString, ByteString)+b_readProcess_ c = do+  (out, err) <- readProcess_ c+  pure (L.toStrict out, L.toStrict err)++b_readProcessStdout_ :: ProcessConfig () () () -> IO ByteString+b_readProcessStdout_ c = do+  out <- readProcessStdout_ c+  pure (L.toStrict out)++--------------------------------------------------------------------------------+-- Temp file operations++temp_withSystemTempFile :: forall a. Text -> (Text -> IO.Handle -> IO a) -> IO a+temp_withSystemTempFile template action = Temp.withSystemTempFile (Text.unpack template) $ \fp h -> action (Text.pack fp) h++temp_withSystemTempDirectory :: forall a. Text -> (Text -> IO a) -> IO a+temp_withSystemTempDirectory template action = Temp.withSystemTempDirectory (Text.unpack template) $ \fp -> action (Text.pack fp)++--------------------------------------------------------------------------------+-- Process operations++process_setWorkingDir :: forall a b c. Text -> ProcessConfig a b c -> ProcessConfig a b c+process_setWorkingDir filepath = Process.setWorkingDir (Text.unpack filepath)++--------------------------------------------------------------------------------+-- Inference type representation++data IRep v+  = IVar v+  | IApp (IRep v) (IRep v)+  | IFun (IRep v) (IRep v)+  | ICon SomeTypeRep+  deriving (Functor, Traversable, Foldable, Eq, Ord, Show)++data ZonkError+  = ZonkKindError+  | AmbiguousMetavar IMetaVar+  deriving (Show)++-- | A complete implementation of conversion from the inferer's type+-- rep to some star type, ready for the type checker.+toSomeTypeRep :: IRep Void -> Either ZonkError SomeTypeRep+toSomeTypeRep t = do+  go t+  where+    go :: IRep Void -> Either ZonkError SomeTypeRep+    go = \case+      IVar v -> pure (absurd v)+      ICon someTypeRep -> pure someTypeRep+      IFun a b -> do+        a' <- go a+        b' <- go b+        case (a', b') of+          (StarTypeRep aRep, StarTypeRep bRep) ->+            pure $ StarTypeRep (Type.Fun aRep bRep)+          _ -> Left ZonkKindError+      IApp f a -> do+        f' <- go f+        a' <- go a+        case applyTypes f' a' of+          Just someTypeRep -> pure someTypeRep+          _ -> Left ZonkKindError++-- | Convert from a type-indexed type to an untyped type.+fromSomeStarType :: forall void. SomeStarType -> IRep void+fromSomeStarType (SomeStarType r) = fromSomeType (SomeTypeRep r)++fromSomeType :: forall void. SomeTypeRep -> IRep void+fromSomeType (SomeTypeRep r) = go r+  where+    go :: forall a. TypeRep a -> IRep void+    go = \case+      Type.Fun a b -> IFun (go a) (go b)+      Type.App a b -> IApp (go a) (go b)+      rep@Type.Con {} -> ICon (SomeTypeRep rep)++--------------------------------------------------------------------------------+-- Inference elaboration phase++data IMetaVar = IMetaVar0 {index :: Int, srcSpanInfo :: HSE.SrcSpanInfo}+  deriving (Ord, Eq, Show)++data Elaborate = Elaborate+  { counter :: Int,+    equalities :: Set (Equality (IRep IMetaVar))+  }++data Equality a = Equality HSE.SrcSpanInfo a a+  deriving (Show, Functor)++-- Equality/ordering that is symmetric.+instance (Ord a) => Eq (Equality a) where+  Equality _ a b == Equality _ c d = Set.fromList [a, b] == Set.fromList [c, d]++instance (Ord a) => Ord (Equality a) where+  Equality _ a b `compare` Equality _ c d = Set.fromList [a, b] `compare` Set.fromList [c, d]++data ElaborateError = UnsupportedTupleSize | BadInstantiationBug | VariableNotInScope String+  deriving (Show)++-- | Elaboration phase.+--+-- Note: The input term contains no metavars. There are just some+-- UForalls, which have poly types, and those are instantiated into+-- metavars.+--+-- Output type /does/ contain meta vars.+elaborate :: UTerm () -> Either ElaborateError (UTerm (IRep IMetaVar), Set (Equality (IRep IMetaVar)))+elaborate = fmap getEqualities . flip runStateT empty' . flip runReaderT mempty . go+  where+    empty' = Elaborate {counter = 0, equalities = mempty}+    getEqualities (term, Elaborate {equalities}) = (term, equalities)+    go :: UTerm () -> ReaderT (Map String (IRep IMetaVar)) (StateT Elaborate (Either ElaborateError)) (UTerm (IRep IMetaVar))+    go = \case+      USig l () e ty -> do+        e' <- go e+        equal l (typeOf e') (fromSomeStarType ty)+        pure $ e'+      UVar l () string -> do+        env <- ask+        ty <- case Map.lookup string env of+          Just typ -> pure typ+          Nothing -> lift $ lift $ Left $ VariableNotInScope string+        pure $ UVar l ty string+      UApp l () f x -> do+        f' <- go f+        x' <- go x+        b <- fmap IVar $ freshIMetaVar l+        equal l (typeOf f') (IFun (typeOf x') b)+        pure $ UApp l b f' x'+      ULam l () binding mstarType body -> do+        a <- case mstarType of+          Just ty -> pure $ fromSomeStarType ty+          Nothing -> fmap IVar $ freshIMetaVar l+        vars <- lift $ bindingVars l a binding+        body' <- local (Map.union vars) $ go body+        let ty = IFun a (typeOf body')+        pure $ ULam l ty binding mstarType body'+      UForall prim l () types forall' uniqs polyRep _ -> do+        -- Generate variables for each unique.+        vars <- for uniqs \uniq -> do+          v <- freshIMetaVar l+          pure (uniq, v)+        -- Fill in the polyRep with the metavars.+        monoType <- for polyRep \uniq ->+          case List.lookup uniq vars of+            Nothing -> lift $ lift $ Left $ BadInstantiationBug+            Just var -> pure var+        -- Order of types is position-dependent, apply the ones we have.+        for_ (zip vars types) \((_uniq, var), someTypeRep) ->+          equal l (fromSomeType someTypeRep) (IVar var)+        -- Done!+        pure $ UForall prim l monoType types forall' uniqs polyRep (map (IVar . snd) vars)++bindingVars :: HSE.SrcSpanInfo -> IRep IMetaVar -> Binding -> StateT Elaborate (Either ElaborateError) (Map String (IRep IMetaVar))+bindingVars _ irep (Singleton name) = pure $ Map.singleton name irep+bindingVars l tupleVar (Tuple names) = do+  varsTypes <- for names \name -> fmap (name,) (fmap IVar (freshIMetaVar l))+  -- it's a left-fold:+  -- IApp (IApp (ICon (,)) x) y+  cons <- makeCons+  equal l tupleVar $ foldl IApp (ICon cons) (map snd varsTypes)+  pure $ Map.fromList varsTypes+  where+    makeCons = case length names of+      2 -> pure $ SomeTypeRep (typeRep @(,))+      3 -> pure $ SomeTypeRep (typeRep @(,,))+      4 -> pure $ SomeTypeRep (typeRep @(,,,))+      _ -> lift $ Left $ UnsupportedTupleSize++equal :: (MonadState Elaborate m) => HSE.SrcSpanInfo -> IRep IMetaVar -> IRep IMetaVar -> m ()+equal l x y = modify \elaborate' -> elaborate' {equalities = elaborate'.equalities <> Set.singleton (Equality l x y)}++freshIMetaVar :: (MonadState Elaborate m) => HSE.SrcSpanInfo -> m IMetaVar+freshIMetaVar srcSpanInfo = do+  Elaborate {counter} <- get+  modify \elaborate' -> elaborate' {counter = counter + 1}+  pure $ IMetaVar0 counter srcSpanInfo++--------------------------------------------------------------------------------+-- Unification++data UnifyError+  = OccursCheck+  | TypeMismatch HSE.SrcSpanInfo (IRep IMetaVar) (IRep IMetaVar)+  deriving (Show)++-- | Unification of equality constraints, a ~ b, to substitutions.+unify :: Set (Equality (IRep IMetaVar)) -> Either UnifyError (Map IMetaVar (IRep IMetaVar))+unify = foldM update mempty+  where+    update existing equality =+      fmap+        (`extends` existing)+        (examine (fmap (substitute existing) equality))+    examine (Equality l a b)+      | a == b = pure mempty+      | IVar ivar <- a = bindMetaVar ivar b+      | IVar ivar <- b = bindMetaVar ivar a+      | IFun a1 b1 <- a,+        IFun a2 b2 <- b =+          unify (Set.fromList [Equality l a1 a2, Equality l b1 b2])+      | IApp a1 b1 <- a,+        IApp a2 b2 <- b =+          unify (Set.fromList [Equality l a1 a2, Equality l b1 b2])+      | ICon x <- a,+        ICon y <- b =+          if x == y+            then pure mempty+            else Left $ TypeMismatch l a b+      | otherwise = Left $ TypeMismatch l a b++-- | Apply new substitutions to the old ones, and expand the set to old+new.+extends :: Map IMetaVar (IRep IMetaVar) -> Map IMetaVar (IRep IMetaVar) -> Map IMetaVar (IRep IMetaVar)+extends new old = fmap (substitute new) old <> new++-- | Apply any substitutions to the type, where there are metavars.+substitute :: Map IMetaVar (IRep IMetaVar) -> IRep IMetaVar -> IRep IMetaVar+substitute subs = go+  where+    go = \case+      IVar v -> case Map.lookup v subs of+        Nothing -> IVar v+        Just ty -> ty+      ICon c -> ICon c+      IFun a b -> IFun (go a) (go b)+      IApp a b -> IApp (go a) (go b)++-- | Do an occurrs check, if all good, return a binding.+bindMetaVar ::+  IMetaVar ->+  IRep IMetaVar ->+  Either UnifyError (Map IMetaVar (IRep IMetaVar))+bindMetaVar var typ+  | occurs var typ = Left OccursCheck+  | otherwise = pure $ Map.singleton var typ++-- | Occurs check.+occurs :: IMetaVar -> IRep IMetaVar -> Bool+occurs ivar = any (== ivar)++-- | Remove any metavars from the type.+--+-- <https://stackoverflow.com/questions/31889048/what-does-the-ghc-source-mean-by-zonk>+zonk :: IRep IMetaVar -> Either ZonkError (IRep Void)+zonk = \case+  IVar var -> Left $ AmbiguousMetavar var+  ICon c -> pure $ ICon c+  IFun a b -> IFun <$> zonk a <*> zonk b+  IApp a b -> IApp <$> zonk a <*> zonk b++--------------------------------------------------------------------------------+-- Parse with #!/shebangs++data File = File+  { terms :: [(String, HSE.Exp HSE.SrcSpanInfo)],+    types :: [(String, HSE.Type HSE.SrcSpanInfo)]+  }+  deriving (Eq, Show)++-- Parse a file into a list of decls, but strip shebangs.+parseFile :: StatsEnabled -> String -> IO (Either String File)+parseFile stats filePath = do+  t0 <- getTime+  string <- ByteString.readFile filePath+  t1 <- getTime+  emitStat stats "read_file" (t1 - t0)+  parseText stats filePath $ Text.decodeUtf8 string++parseText :: StatsEnabled -> FilePath -> Text -> IO (Either String File)+parseText stats filePath text = do+  t1 <- getTime+  case HSE.parseModuleWithMode+    HSE.defaultParseMode+      { HSE.parseFilename = filePath,+        HSE.extensions =+          HSE.extensions HSE.defaultParseMode+            ++ [ HSE.EnableExtension HSE.PatternSignatures,+                 HSE.EnableExtension HSE.DataKinds,+                 HSE.EnableExtension HSE.BlockArguments,+                 HSE.EnableExtension HSE.TypeApplications,+                 HSE.EnableExtension HSE.NamedFieldPuns+               ]+      }+    (Text.unpack (dropShebang text)) of+    HSE.ParseFailed l e -> pure $ Left $ "Parse error: " <> HSE.prettyPrint l <> ": " <> e+    HSE.ParseOk !file -> do+      t2 <- getTime+      emitStat stats "parse_module_with_mode" (t2 - t1)+      case parseModule file of+        HSE.ParseFailed l e ->+          pure $ Left $ "Parse error: " <> HSE.prettyPrint l <> ": " <> e+        HSE.ParseOk !file' -> do+          t3 <- getTime+          emitStat stats "resolve_module" (t3 - t2)+          pure $ Right file'++-- This should be quite efficient because it's essentially a pointer+-- increase. It leaves the \n so that line numbers are intact.+dropShebang :: Text -> Text+dropShebang t = Maybe.fromMaybe t do+  rest <- Text.stripPrefix "#!" t+  pure $ Text.dropWhile (/= '\n') rest++--------------------------------------------------------------------------------+-- Records++data Tagged (s :: Symbol) a = Tagged (SSymbol s) a++data List = NilL | ConsL Symbol Type List++data Record (xs :: List) where+  NilR :: Record 'NilL+  ConsR :: forall k a xs. SSymbol k -> a -> Record xs -> Record (ConsL k a xs)++-- | Build up a type-safe getter.+makeAccessor ::+  forall k r0 a t.+  TypeRep (k :: Symbol) ->+  TypeRep (r0 :: List) ->+  TypeRep a ->+  TypeRep t ->+  Maybe (Tagged t (Record (r0 :: List)) -> a)+makeAccessor k r0 a _ = do+  accessor <- go r0+  pure \(Tagged _ r) -> accessor r+  where+    go :: TypeRep (r :: List) -> Maybe (Record (r :: List) -> a)+    go r =+      case Type.eqTypeRep r (Type.TypeRep @NilL) of+        Just {} -> Nothing+        Nothing ->+          case r of+            Type.App (Type.App (Type.App _ sym) typ) r'+              | Just Type.HRefl <- Type.eqTypeRep (typeRepKind typ) (typeRep @Type),+                Just Type.HRefl <- Type.eqTypeRep (typeRepKind sym) (typeRep @Symbol),+                Just Type.HRefl <- Type.eqTypeRep (typeRepKind r') (typeRep @List) ->+                  case (Type.eqTypeRep k sym, Type.eqTypeRep a typ) of+                    (Just Type.HRefl, Just Type.HRefl) ->+                      pure \(ConsR _k v _xs) -> v+                    _ -> do+                      accessor <- go r'+                      pure \case+                        ConsR _k _a xs -> accessor xs+            _ -> Nothing++-- | Build up a type-safe setter.+makeSetter ::+  forall k r0 a t.+  TypeRep (k :: Symbol) ->+  TypeRep (r0 :: List) ->+  TypeRep a ->+  TypeRep t ->+  Maybe (a -> Tagged t (Record (r0 :: List)) -> Tagged t (Record (r0 :: List)))+makeSetter k r0 a _ = do+  setter <- go r0+  pure \a' (Tagged t r) -> Tagged t (setter a' r)+  where+    go :: TypeRep (r :: List) -> Maybe (a -> Record (r :: List) -> Record (r :: List))+    go r =+      case Type.eqTypeRep r (Type.TypeRep @NilL) of+        Just {} -> Nothing+        Nothing ->+          case r of+            Type.App (Type.App (Type.App _ sym) typ) r'+              | Just Type.HRefl <- Type.eqTypeRep (typeRepKind typ) (typeRep @Type),+                Just Type.HRefl <- Type.eqTypeRep (typeRepKind sym) (typeRep @Symbol),+                Just Type.HRefl <- Type.eqTypeRep (typeRepKind r') (typeRep @List) ->+                  case (Type.eqTypeRep k sym, Type.eqTypeRep a typ) of+                    (Just Type.HRefl, Just Type.HRefl) ->+                      pure \a' (ConsR k' _a xs) -> ConsR k' a' xs+                    _ -> do+                      setter <- go r'+                      pure \a' (ConsR k' a0 xs) -> ConsR k' a0 (setter a' xs)+            _ -> Nothing++-- | Simply re-uses makeAccessor and makeSetter.+makeModify ::+  forall k r0 a t.+  TypeRep (k :: Symbol) ->+  TypeRep (r0 :: List) ->+  TypeRep a ->+  TypeRep t ->+  Maybe ((a -> a) -> Tagged t (Record (r0 :: List)) -> Tagged t (Record (r0 :: List)))+makeModify k0 r0 a0 t0 = do+  getter <- makeAccessor k0 r0 a0 t0+  setter <- makeSetter k0 r0 a0 t0+  pure \f record -> setter (f (getter record)) record++--------------------------------------------------------------------------------+-- Variants++-- | A variant; one of the given choices.+data Variant (xs :: List) where+  LeftV :: forall k a xs. SSymbol k -> a -> Variant (ConsL k a xs)+  RightV :: forall k a xs k'' a''. Variant (ConsL k'' a'' xs) -> Variant (ConsL k a (ConsL k'' a'' xs))++-- | Accessor of a given variant. A record whose fields all correspond+-- to the constructors of a sum type, and whose types are all `a ->+-- r` instead of `a`.+data Accessor (xs :: List) r where+  NilA :: Accessor 'NilL r+  ConsA :: forall k a r xs. (a -> r) -> Accessor xs r -> Accessor (ConsL k a xs) r+  WildA :: forall r xs. r -> Accessor xs r++-- | Run a total case-analysis against a variant, given an accessor+-- record.+runAccessor :: Tagged s (Variant xs) -> Accessor xs r -> r+runAccessor (Tagged _ (LeftV _k a)) (ConsA f _) = f a+runAccessor (Tagged t (RightV xs)) (ConsA _ ys) = runAccessor (Tagged t xs) ys+runAccessor _ (WildA r) = r++--------------------------------------------------------------------------------+-- Pretty printing++-- | Convenience.+prettyString :: (Pretty a) => a -> String+prettyString =+  Text.unpack . Text.decodeUtf8 . L.toStrict . ByteString.toLazyByteString . pretty++class Pretty a where+  pretty :: a -> ByteString.Builder++instance Pretty String where+  pretty r =+    ByteString.byteString (Text.encodeUtf8 $ Text.pack r)++instance Pretty SomeTypeRep where+  pretty r =+    ByteString.byteString (Text.encodeUtf8 $ Text.pack $ show r)++instance Pretty (TypeRep t) where+  pretty r =+    ByteString.byteString (Text.encodeUtf8 $ Text.pack $ show r)++instance Pretty IMetaVar where+  pretty (IMetaVar0 i _) =+    "t"+      <> ByteString.byteString (Text.encodeUtf8 $ Text.pack $ show i)++instance Pretty (UTerm t) where+  pretty = \case+    UVar _ _ v -> pretty v+    UApp _ _ f x -> "(" <> pretty f <> " " <> pretty x <> ")"+    USig _ _ f s -> "(" <> pretty f <> " :: " <> pretty s <> ")"+    UForall prim _ _ _ _ _ _ _ -> pretty prim+    ULam _ _ binding _ t ->+      "(\\" <> pretty binding <> " -> " <> pretty t <> ")"++instance Pretty Prim where+  pretty = \case+    LitP p -> pretty $ HSE.prettyPrint p+    NameP s -> pretty s+    UnitP -> "()"+    SSymbolP s -> "SSymbol " <> pretty s++instance Pretty Binding where+  pretty = \case+    Singleton v -> pretty v+    Tuple xs -> "(" <> mconcat (List.intersperse ", " (map pretty xs)) <> ")"++instance (Pretty a) => Pretty (IRep a) where+  pretty = \case+    IVar a -> pretty a+    ICon a -> pretty a+    IApp f x -> "(" <> pretty f <> " " <> pretty x <> ")"+    IFun a b -> "(" <> pretty a <> " -> " <> pretty b <> ")"++instance Pretty ZonkError where+  pretty = \case+    ZonkKindError -> "Kind error."+    AmbiguousMetavar imetavar ->+      "Ambiguous meta variable: "+        <> pretty imetavar+        <> "\n"+        <> "arising from "+        <> pretty imetavar.srcSpanInfo++instance Pretty ElaborateError where+  pretty = \case+    UnsupportedTupleSize -> "That tuple size is not supported."+    BadInstantiationBug -> "BUG: BadInstantiationBug. Please report."+    VariableNotInScope s -> "Variable not in scope: " <> pretty s++instance Pretty UnifyError where+  pretty = \case+    OccursCheck -> "Occurs check failed: Infinite type."+    TypeMismatch l a b ->+      mconcat $+        List.intersperse+          "\n\n"+          [ "Couldn't match type",+            "  " <> pretty a,+            "against type",+            "  " <> pretty b,+            "arising from " <> pretty l+          ]++instance Pretty HSE.SrcSpanInfo where+  pretty l =+    mconcat+      [ pretty (HSE.fileName l),+        ":",+        pretty $ show $ HSE.startLine l,+        ":",+        pretty $ show $ HSE.startColumn l+      ]++instance Pretty TypeCheckError where+  pretty = \case+    NotInScope s -> "Not in scope: " <> pretty s+    TupleTypeMismatch -> "Tuple type mismatch!"+    TypeCheckMismatch -> "Type check mismatch."+    TupleTypeTooBig -> "Tuple type is too big."+    TypeOfApplicandIsNotFunction -> "Type of application is not a function."+    LambdaIsNotAFunBug -> "BUG: LambdaIsNotAFunBug. Please report."+    InferredCheckedDisagreeBug -> "BUG: Inferred type disagrees with checked type. Please report."+    LambdaMustBeStarBug -> "BUG: Lambda should be of kind *, but isn't. Please report."+    ConstraintResolutionProblem loc forall' msg ->+      mconcat $+        List.intersperse+          "\n\n"+          [ "Couldn't resolve constraint",+            "  " <> pretty (showR forall'),+            "due to problem",+            "  " <> pretty msg,+            "arising from " <> pretty loc+          ]++instance Pretty DesugarError where+  pretty = \case+    InvalidConstructor c -> "Invalid constructor: " <> pretty c+    InvalidVariable c -> "Invalid variable: " <> pretty c+    UnknownType t -> "Unknown type: " <> pretty t+    UnsupportedSyntax s -> "Unsupported syntax: " <> pretty s+    BadParameterSyntax s -> "Bad parameter syntax: " <> pretty s+    KindError -> "Kind error."+    BadDoNotation -> "Bad do notation."+    TupleTooBig -> "That tuple size is not supported."+    UnsupportedLiteral -> "That literal type is not supported."++instance Pretty InferError where+  pretty = \case+    UnifyError e -> "Unification error: " <> pretty e+    ZonkError e -> "Zonk error: " <> pretty e+    ElabError e -> "Elaboration error: " <> pretty e++--------------------------------------------------------------------------------+-- Generate docs++_generateApiDocs :: IO ()+_generateApiDocs = do+  css <- Text.readFile "docs/style.css"+  js <- Text.readFile "docs/index.js"+  Lucid.renderToFile "docs/api/index.html" do+    doctypehtml_ do+      style_ css+      head_ do+        title_ "Hell's API"+      body_ do+        h1_ "Hell's API"+        h2_ $ do "Version: "; toHtml hellVersion+        p_ $ a_ [href_ "../"] $ "Back to homepage"+        input_ [type_ "text", id_ "search", placeholder_ "Filter..."]+        h2_ "Types"+        let excludeHidden = filter (not . List.isPrefixOf "hell:Hell." . fst)+        ul_ do+          for_ (excludeHidden $ Map.toList supportedTypeConstructors) typeConsToHtml+        h2_ "Terms"+        let groups =+              excludeHidden $+                Map.toList $+                  fmap (Left . snd) $+                    supportedLits+        let groups' =+              excludeHidden $+                Map.toList $+                  fmap (\(_, _, _, ty) -> Right ty) polyLits+        for_ (List.groupBy (Function.on (==) (takeWhile (/= '.') . fst)) $ List.sortOn fst $ groups <> groups') \group -> do+          h3_ [class_ "searchableHeading"] $ for_ (take 1 group) \(x, _) -> toHtml $ takeWhile (/= '.') x+          ul_ do+            for_ group \(x, a) -> case a of+              Left e -> litToHtml (x, e)+              Right e -> polyToHtml (x, e)+      script_ [id_ "searchIndex"] $ Json.encode makeSearchIndex+      script_ [type_ "text/javascript"] js++makeSearchIndex :: Json.Value+makeSearchIndex = Json.Array $ typeConstructorsIndex <> litsIndex <> polysIndex+  where+    typeConstructorsIndex =+      Vector.fromList $+        map+          ( \(name, _) ->+              Json.object+                [ ("elementId", Json.String $ nameToElementId name),+                  ("text", Json.String $ Text.pack name)+                ]+          )+          (Map.toList supportedTypeConstructors)+    litsIndex =+      Vector.fromList $+        map+          ( \(name, _) ->+              Json.object+                [ ("elementId", Json.String $ nameToElementId name),+                  ("text", Json.String $ Text.pack name)+                ]+          )+          (Map.toList supportedLits)+    polysIndex =+      Vector.fromList $+        map+          ( \(name, _) ->+              Json.object+                [ ("elementId", Json.String $ nameToElementId name),+                  ("text", Json.String $ Text.pack name)+                ]+          )+          (Map.toList polyLits)++nameToElementId :: String -> Text+nameToElementId = Text.pack++typeConsToHtml :: (String, SomeTypeRep) -> Html ()+typeConsToHtml (name, SomeTypeRep rep) =+  li_ [id_ (nameToElementId name), class_ "searchable"] $ do+    code_ do+      em_ "data "+      strong_ $ toHtml name+      em_ " :: "+      toHtml $ prettyString $ typeRepKind rep++litToHtml :: (String, SomeTypeRep) -> Html ()+litToHtml (name, SomeTypeRep rep) =+  li_ [id_ (nameToElementId name), class_ "searchable"] $ do+    code_ do+      strong_ $ toHtml name+      em_ " :: "+      toHtml $ prettyString $ rep++polyToHtml :: (String, TH.Type) -> Html ()+polyToHtml (name, ty) =+  li_ [id_ (nameToElementId name), class_ "searchable"] $ do+    code_ do+      strong_ $ toHtml name+      em_ " :: "+      toHtml $ TH.pprint $ cleanUpTHType ty++cleanUpTHType :: TH.Type -> TH.Type+cleanUpTHType = SYB.everywhere unqualify+  where+    unqualify :: forall a. (Type.Typeable a) => a -> a+    unqualify a =+      case Type.eqTypeRep (Type.typeRep @a) (Type.typeRep @TH.Name) of+        Nothing -> a+        Just Type.HRefl ->+          TH.mkName $ TH.nameBase a++--------------------------------------------------------------------------------+-- Test suite++specMain :: IO ()+specMain = hspec spec++spec :: Spec+spec = do+  parseSpec+  freeVariablesSpec+  anyCyclesSpec+  desugarTypeSpec++parseSpec :: Spec+parseSpec = do+  describe "parse" do+    it "dropShebang" do+      r <- parseText NoStats "x.hell" "#!/bin/env hell\nx = z X {a,b}"+      shouldSatisfy r Either.isRight+    it "empty file parses" do+      r <- parseText NoStats "x.hell" ""+      shouldSatisfy r Either.isRight+    it "PatternSignatures" do+      r <- parseText NoStats "x.hell" "x = \\(z :: Int) -> z"+      shouldSatisfy r Either.isRight+    it "TypeApplications" do+      r <- parseText NoStats "x.hell" "x = z @T"+      shouldSatisfy r Either.isRight+    it "DataKinds" do+      r <- parseText NoStats "x.hell" "x = z @\"foo\""+      shouldSatisfy r Either.isRight+    it "BlockArguments" do+      r <- parseText NoStats "x.hell" "x = z do y"+      shouldSatisfy r Either.isRight+    it "NamedFieldPuns" do+      r <- parseText NoStats "x.hell" "x = z X {a,b}"+      shouldSatisfy r Either.isRight++anyCyclesSpec :: Spec+anyCyclesSpec = do+  it "anyCycles" do+    shouldBe (try [("foo", "\\z -> x * Z.y"), ("bar", "\\z -> Main.bar * Z.y")]) True+    shouldBe (try [("foo", "\\z -> Main.bar * Z.y"), ("bar", "\\z -> Main.foo * Z.y")]) True+    shouldBe (try [("foo", "\\z -> x * Z.y"), ("bar", "\\z -> Main.mu * Z.y")]) False+    shouldBe (try [("foo", "\\z -> x * Z.y"), ("bar", "\\z -> Main.foo * Z.y")]) False+  where+    try named =+      case traverse (\(n, e) -> (n,) <$> HSE.parseExp e) named of+        HSE.ParseOk decls -> anyCycles decls+        _ -> error "Parse failed."++freeVariablesSpec :: Spec+freeVariablesSpec = do+  it "freeVariables" $ shouldBe (try "\\z -> Main.x * Z.y / Main.P") ["x", "P"]+  where+    try e = case fmap freeVariables $ HSE.parseExp e of+      HSE.ParseOk names -> names+      _ -> error "Parse failed."++desugarTypeSpec :: Spec+desugarTypeSpec = do+  it "desugarType" $ do+    shouldBe (try "Bool") (Right (SomeStarType $ typeRep @Bool))+    shouldBe (try "Int") (Right (SomeStarType $ typeRep @Int))+    shouldBe (try "Bool -> Int") (Right (SomeStarType $ typeRep @(Bool -> Int)))+    shouldBe (try "()") (Right (SomeStarType $ typeRep @()))+    shouldBe (try "[Int]") (Right (SomeStarType $ typeRep @[Int]))+  where+    try e = case fmap (desugarStarType mempty) $ HSE.parseType e of+      HSE.ParseOk r -> r+      _ -> error "Parse failed."