1module Language.PureScript.Environment where 2 3import Prelude.Compat 4import Protolude (ordNub) 5 6import GHC.Generics (Generic) 7import Control.DeepSeq (NFData) 8import Codec.Serialise (Serialise) 9import Data.Aeson ((.=), (.:)) 10import qualified Data.Aeson as A 11import qualified Data.Map as M 12import qualified Data.Set as S 13import Data.Maybe (fromMaybe, mapMaybe) 14import Data.Text (Text) 15import qualified Data.Text as T 16import Data.Tree (Tree, rootLabel) 17import qualified Data.Graph as G 18import Data.Foldable (toList) 19import qualified Data.List.NonEmpty as NEL 20 21import Language.PureScript.AST.SourcePos 22import Language.PureScript.Crash 23import Language.PureScript.Names 24import Language.PureScript.Roles 25import Language.PureScript.TypeClassDictionaries 26import Language.PureScript.Types 27import qualified Language.PureScript.Constants.Prim as C 28 29-- | The @Environment@ defines all values and types which are currently in scope: 30data Environment = Environment 31 { names :: M.Map (Qualified Ident) (SourceType, NameKind, NameVisibility) 32 -- ^ Values currently in scope 33 , types :: M.Map (Qualified (ProperName 'TypeName)) (SourceType, TypeKind) 34 -- ^ Type names currently in scope 35 , dataConstructors :: M.Map (Qualified (ProperName 'ConstructorName)) (DataDeclType, ProperName 'TypeName, SourceType, [Ident]) 36 -- ^ Data constructors currently in scope, along with their associated type 37 -- constructor name, argument types and return type. 38 , roleDeclarations :: M.Map (Qualified (ProperName 'TypeName)) [Role] 39 -- ^ Explicit role declarations currently in scope. Note that this field is 40 -- only used to store declared roles temporarily until they can be checked; 41 -- to find a type's real checked and/or inferred roles, refer to the TypeKind 42 -- in the `types` field. 43 , typeSynonyms :: M.Map (Qualified (ProperName 'TypeName)) ([(Text, Maybe SourceType)], SourceType) 44 -- ^ Type synonyms currently in scope 45 , typeClassDictionaries :: M.Map (Maybe ModuleName) (M.Map (Qualified (ProperName 'ClassName)) (M.Map (Qualified Ident) (NEL.NonEmpty NamedDict))) 46 -- ^ Available type class dictionaries. When looking up 'Nothing' in the 47 -- outer map, this returns the map of type class dictionaries in local 48 -- scope (ie dictionaries brought in by a constrained type). 49 , typeClasses :: M.Map (Qualified (ProperName 'ClassName)) TypeClassData 50 -- ^ Type classes 51 } deriving (Show, Generic) 52 53instance NFData Environment 54 55-- | Information about a type class 56data TypeClassData = TypeClassData 57 { typeClassArguments :: [(Text, Maybe SourceType)] 58 -- ^ A list of type argument names, and their kinds, where kind annotations 59 -- were provided. 60 , typeClassMembers :: [(Ident, SourceType)] 61 -- ^ A list of type class members and their types. Type arguments listed above 62 -- are considered bound in these types. 63 , typeClassSuperclasses :: [SourceConstraint] 64 -- ^ A list of superclasses of this type class. Type arguments listed above 65 -- are considered bound in the types appearing in these constraints. 66 , typeClassDependencies :: [FunctionalDependency] 67 -- ^ A list of functional dependencies for the type arguments of this class. 68 , typeClassDeterminedArguments :: S.Set Int 69 -- ^ A set of indexes of type argument that are fully determined by other 70 -- arguments via functional dependencies. This can be computed from both 71 -- typeClassArguments and typeClassDependencies. 72 , typeClassCoveringSets :: S.Set (S.Set Int) 73 -- ^ A sets of arguments that can be used to infer all other arguments. 74 , typeClassIsEmpty :: Bool 75 -- ^ Whether or not dictionaries for this type class are necessarily empty. 76 } deriving (Show, Generic) 77 78instance NFData TypeClassData 79 80-- | A functional dependency indicates a relationship between two sets of 81-- type arguments in a class declaration. 82data FunctionalDependency = FunctionalDependency 83 { fdDeterminers :: [Int] 84 -- ^ the type arguments which determine the determined type arguments 85 , fdDetermined :: [Int] 86 -- ^ the determined type arguments 87 } deriving (Show, Generic) 88 89instance NFData FunctionalDependency 90instance Serialise FunctionalDependency 91 92instance A.FromJSON FunctionalDependency where 93 parseJSON = A.withObject "FunctionalDependency" $ \o -> 94 FunctionalDependency 95 <$> o .: "determiners" 96 <*> o .: "determined" 97 98instance A.ToJSON FunctionalDependency where 99 toJSON FunctionalDependency{..} = 100 A.object [ "determiners" .= fdDeterminers 101 , "determined" .= fdDetermined 102 ] 103 104-- | The initial environment with no values and only the default javascript types defined 105initEnvironment :: Environment 106initEnvironment = Environment M.empty allPrimTypes M.empty M.empty M.empty M.empty allPrimClasses 107 108-- | A constructor for TypeClassData that computes which type class arguments are fully determined 109-- and argument covering sets. 110-- Fully determined means that this argument cannot be used when selecting a type class instance. 111-- A covering set is a minimal collection of arguments that can be used to find an instance and 112-- therefore determine all other type arguments. 113-- 114-- An example of the difference between determined and fully determined would be with the class: 115-- ```class C a b c | a -> b, b -> a, b -> c``` 116-- In this case, `a` must differ when `b` differs, and vice versa - each is determined by the other. 117-- Both `a` and `b` can be used in selecting a type class instance. However, `c` cannot - it is 118-- fully determined by `a` and `b`. 119-- 120-- Define a graph of type class arguments with edges being fundep determiners to determined. Each 121-- argument also has a self looping edge. 122-- An argument is fully determined if doesn't appear at the start of a path of strongly connected components. 123-- An argument is not fully determined otherwise. 124-- 125-- The way we compute this is by saying: an argument X is fully determined if there are arguments that 126-- determine X that X does not determine. This is the same thing: everything X determines includes everything 127-- in its SCC, and everything determining X is either before it in an SCC path, or in the same SCC. 128makeTypeClassData 129 :: [(Text, Maybe SourceType)] 130 -> [(Ident, SourceType)] 131 -> [SourceConstraint] 132 -> [FunctionalDependency] 133 -> Bool 134 -> TypeClassData 135makeTypeClassData args m s deps = TypeClassData args m s deps determinedArgs coveringSets 136 where 137 argumentIndices = [0 .. length args - 1] 138 139 -- each argument determines themselves 140 identities = (\i -> (i, [i])) <$> argumentIndices 141 142 -- list all the edges in the graph: for each fundep an edge exists for each determiner to each determined 143 contributingDeps = M.fromListWith (++) $ identities ++ do 144 fd <- deps 145 src <- fdDeterminers fd 146 (src, fdDetermined fd) : map (, []) (fdDetermined fd) 147 148 -- build a graph of which arguments determine other arguments 149 (depGraph, fromVertex, fromKey) = G.graphFromEdges ((\(n, v) -> (n, n, ordNub v)) <$> M.toList contributingDeps) 150 151 -- do there exist any arguments that contribute to `arg` that `arg` doesn't contribute to 152 isFunDepDetermined :: Int -> Bool 153 isFunDepDetermined arg = case fromKey arg of 154 Nothing -> internalError "Unknown argument index in makeTypeClassData" 155 Just v -> let contributesToVar = G.reachable (G.transposeG depGraph) v 156 varContributesTo = G.reachable depGraph v 157 in any (`notElem` varContributesTo) contributesToVar 158 159 -- find all the arguments that are determined 160 determinedArgs :: S.Set Int 161 determinedArgs = S.fromList $ filter isFunDepDetermined argumentIndices 162 163 argFromVertex :: G.Vertex -> Int 164 argFromVertex index = let (_, arg, _) = fromVertex index in arg 165 166 isVertexDetermined :: G.Vertex -> Bool 167 isVertexDetermined = isFunDepDetermined . argFromVertex 168 169 -- from an scc find the non-determined args 170 sccNonDetermined :: Tree G.Vertex -> Maybe [Int] 171 sccNonDetermined tree 172 -- if any arg in an scc is determined then all of them are 173 | isVertexDetermined (rootLabel tree) = Nothing 174 | otherwise = Just (argFromVertex <$> toList tree) 175 176 -- find the covering sets 177 coveringSets :: S.Set (S.Set Int) 178 coveringSets = let funDepSets = sequence (mapMaybe sccNonDetermined (G.scc depGraph)) 179 in S.fromList (S.fromList <$> funDepSets) 180 181-- | The visibility of a name in scope 182data NameVisibility 183 = Undefined 184 -- ^ The name is defined in the current binding group, but is not visible 185 | Defined 186 -- ^ The name is defined in the another binding group, or has been made visible by a function binder 187 deriving (Show, Eq, Generic) 188 189instance NFData NameVisibility 190instance Serialise NameVisibility 191 192-- | A flag for whether a name is for an private or public value - only public values will be 193-- included in a generated externs file. 194data NameKind 195 = Private 196 -- ^ A private value introduced as an artifact of code generation (class instances, class member 197 -- accessors, etc.) 198 | Public 199 -- ^ A public value for a module member or foreign import declaration 200 | External 201 -- ^ A name for member introduced by foreign import 202 deriving (Show, Eq, Generic) 203 204instance NFData NameKind 205instance Serialise NameKind 206 207-- | The kinds of a type 208data TypeKind 209 = DataType DataDeclType [(Text, Maybe SourceType, Role)] [(ProperName 'ConstructorName, [SourceType])] 210 -- ^ Data type 211 | TypeSynonym 212 -- ^ Type synonym 213 | ExternData [Role] 214 -- ^ Foreign data 215 | LocalTypeVariable 216 -- ^ A local type variable 217 | ScopedTypeVar 218 -- ^ A scoped type variable 219 deriving (Show, Eq, Generic) 220 221instance NFData TypeKind 222instance Serialise TypeKind 223 224-- | The type ('data' or 'newtype') of a data type declaration 225data DataDeclType 226 = Data 227 -- ^ A standard data constructor 228 | Newtype 229 -- ^ A newtype constructor 230 deriving (Show, Eq, Ord, Generic) 231 232instance NFData DataDeclType 233instance Serialise DataDeclType 234 235showDataDeclType :: DataDeclType -> Text 236showDataDeclType Data = "data" 237showDataDeclType Newtype = "newtype" 238 239instance A.ToJSON DataDeclType where 240 toJSON = A.toJSON . showDataDeclType 241 242instance A.FromJSON DataDeclType where 243 parseJSON = A.withText "DataDeclType" $ \case 244 "data" -> return Data 245 "newtype" -> return Newtype 246 other -> fail $ "invalid type: '" ++ T.unpack other ++ "'" 247 248-- | Construct a ProperName in the Prim module 249primName :: Text -> Qualified (ProperName a) 250primName = Qualified (Just C.Prim) . ProperName 251 252-- | Construct a 'ProperName' in the @Prim.NAME@ module. 253primSubName :: Text -> Text -> Qualified (ProperName a) 254primSubName sub = 255 Qualified (Just $ ModuleName $ C.prim <> "." <> sub) . ProperName 256 257primKind :: Text -> SourceType 258primKind = primTy 259 260primSubKind :: Text -> Text -> SourceType 261primSubKind sub = TypeConstructor nullSourceAnn . primSubName sub 262 263-- | Kind of ground types 264kindType :: SourceType 265kindType = primKind C.typ 266 267kindConstraint :: SourceType 268kindConstraint = primKind C.constraint 269 270kindSymbol :: SourceType 271kindSymbol = primKind C.symbol 272 273kindDoc :: SourceType 274kindDoc = primSubKind C.typeError C.doc 275 276kindOrdering :: SourceType 277kindOrdering = primSubKind C.moduleOrdering C.kindOrdering 278 279kindRowList :: SourceType -> SourceType 280kindRowList = TypeApp nullSourceAnn (primSubKind C.moduleRowList C.kindRowList) 281 282kindRow :: SourceType -> SourceType 283kindRow = TypeApp nullSourceAnn (primKind C.row) 284 285kindOfREmpty :: SourceType 286kindOfREmpty = tyForall "k" kindType (kindRow (tyVar "k")) 287 288-- | Construct a type in the Prim module 289primTy :: Text -> SourceType 290primTy = TypeConstructor nullSourceAnn . primName 291 292-- | Type constructor for functions 293tyFunction :: SourceType 294tyFunction = primTy "Function" 295 296-- | Type constructor for strings 297tyString :: SourceType 298tyString = primTy "String" 299 300-- | Type constructor for strings 301tyChar :: SourceType 302tyChar = primTy "Char" 303 304-- | Type constructor for numbers 305tyNumber :: SourceType 306tyNumber = primTy "Number" 307 308-- | Type constructor for integers 309tyInt :: SourceType 310tyInt = primTy "Int" 311 312-- | Type constructor for booleans 313tyBoolean :: SourceType 314tyBoolean = primTy "Boolean" 315 316-- | Type constructor for arrays 317tyArray :: SourceType 318tyArray = primTy "Array" 319 320-- | Type constructor for records 321tyRecord :: SourceType 322tyRecord = primTy "Record" 323 324tyVar :: Text -> SourceType 325tyVar = TypeVar nullSourceAnn 326 327tyForall :: Text -> SourceType -> SourceType -> SourceType 328tyForall var k ty = ForAll nullSourceAnn var (Just k) ty Nothing 329 330-- | Smart constructor for function types 331function :: SourceType -> SourceType -> SourceType 332function = TypeApp nullSourceAnn . TypeApp nullSourceAnn tyFunction 333 334-- To make reading the kind signatures below easier 335(-:>) :: SourceType -> SourceType -> SourceType 336(-:>) = function 337infixr 4 -:> 338 339primClass :: Qualified (ProperName 'TypeName) -> (SourceType -> SourceType) -> [(Qualified (ProperName 'TypeName), (SourceType, TypeKind))] 340primClass name mkKind = 341 [ let k = mkKind kindConstraint 342 in (name, (k, ExternData (nominalRolesForKind k))) 343 , let k = mkKind kindType 344 in (dictTypeName <$> name, (k, TypeSynonym)) 345 ] 346 347-- | The primitive types in the external environment with their 348-- associated kinds. There are also pseudo `Fail`, `Warn`, and `Partial` types 349-- that correspond to the classes with the same names. 350primTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceType, TypeKind) 351primTypes = 352 M.fromList 353 [ (primName "Type", (kindType, ExternData [])) 354 , (primName "Constraint", (kindType, ExternData [])) 355 , (primName "Symbol", (kindType, ExternData [])) 356 , (primName "Row", (kindType -:> kindType, ExternData [Phantom])) 357 , (primName "Function", (kindType -:> kindType -:> kindType, ExternData [Representational, Representational])) 358 , (primName "Array", (kindType -:> kindType, ExternData [Representational])) 359 , (primName "Record", (kindRow kindType -:> kindType, ExternData [Representational])) 360 , (primName "String", (kindType, ExternData [])) 361 , (primName "Char", (kindType, ExternData [])) 362 , (primName "Number", (kindType, ExternData [])) 363 , (primName "Int", (kindType, ExternData [])) 364 , (primName "Boolean", (kindType, ExternData [])) 365 , (primName "Partial", (kindConstraint, ExternData [])) 366 ] 367 368-- | This 'Map' contains all of the prim types from all Prim modules. 369allPrimTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceType, TypeKind) 370allPrimTypes = M.unions 371 [ primTypes 372 , primBooleanTypes 373 , primCoerceTypes 374 , primOrderingTypes 375 , primRowTypes 376 , primRowListTypes 377 , primSymbolTypes 378 , primTypeErrorTypes 379 ] 380 381primBooleanTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceType, TypeKind) 382primBooleanTypes = 383 M.fromList 384 [ (primSubName C.moduleBoolean "True", (tyBoolean, ExternData [])) 385 , (primSubName C.moduleBoolean "False", (tyBoolean, ExternData [])) 386 ] 387 388primCoerceTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceType, TypeKind) 389primCoerceTypes = 390 M.fromList $ mconcat 391 [ primClass (primSubName C.moduleCoerce "Coercible") (\kind -> tyForall "k" kindType $ tyVar "k" -:> tyVar "k" -:> kind) 392 ] 393 394primOrderingTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceType, TypeKind) 395primOrderingTypes = 396 M.fromList 397 [ (primSubName C.moduleOrdering "Ordering", (kindType, ExternData [])) 398 , (primSubName C.moduleOrdering "LT", (kindOrdering, ExternData [])) 399 , (primSubName C.moduleOrdering "EQ", (kindOrdering, ExternData [])) 400 , (primSubName C.moduleOrdering "GT", (kindOrdering, ExternData [])) 401 ] 402 403primRowTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceType, TypeKind) 404primRowTypes = 405 M.fromList $ mconcat 406 [ primClass (primSubName C.moduleRow "Union") (\kind -> tyForall "k" kindType $ kindRow (tyVar "k") -:> kindRow (tyVar "k") -:> kindRow (tyVar "k") -:> kind) 407 , primClass (primSubName C.moduleRow "Nub") (\kind -> tyForall "k" kindType $ kindRow (tyVar "k") -:> kindRow (tyVar "k") -:> kind) 408 , primClass (primSubName C.moduleRow "Lacks") (\kind -> tyForall "k" kindType $ kindSymbol -:> kindRow (tyVar "k") -:> kind) 409 , primClass (primSubName C.moduleRow "Cons") (\kind -> tyForall "k" kindType $ kindSymbol -:> tyVar "k" -:> kindRow (tyVar "k") -:> kindRow (tyVar "k") -:> kind) 410 ] 411 412primRowListTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceType, TypeKind) 413primRowListTypes = 414 M.fromList $ 415 [ (primSubName C.moduleRowList "RowList", (kindType -:> kindType, ExternData [Phantom])) 416 , (primSubName C.moduleRowList "Cons", (tyForall "k" kindType $ kindSymbol -:> tyVar "k" -:> kindRowList (tyVar "k") -:> kindRowList (tyVar "k"), ExternData [Phantom, Phantom, Phantom])) 417 , (primSubName C.moduleRowList "Nil", (tyForall "k" kindType $ kindRowList (tyVar "k"), ExternData [])) 418 ] <> mconcat 419 [ primClass (primSubName C.moduleRowList "RowToList") (\kind -> tyForall "k" kindType $ kindRow (tyVar "k") -:> kindRowList (tyVar "k") -:> kind) 420 ] 421 422primSymbolTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceType, TypeKind) 423primSymbolTypes = 424 M.fromList $ mconcat 425 [ primClass (primSubName C.moduleSymbol "Append") (\kind -> kindSymbol -:> kindSymbol -:> kindSymbol -:> kind) 426 , primClass (primSubName C.moduleSymbol "Compare") (\kind -> kindSymbol -:> kindSymbol -:> kindOrdering -:> kind) 427 , primClass (primSubName C.moduleSymbol "Cons") (\kind -> kindSymbol -:> kindSymbol -:> kindSymbol -:> kind) 428 ] 429 430primTypeErrorTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceType, TypeKind) 431primTypeErrorTypes = 432 M.fromList $ 433 [ (primSubName C.typeError "Doc", (kindType, ExternData [])) 434 , (primSubName C.typeError "Fail", (kindDoc -:> kindConstraint, ExternData [Nominal])) 435 , (primSubName C.typeError "Warn", (kindDoc -:> kindConstraint, ExternData [Nominal])) 436 , (primSubName C.typeError "Text", (kindSymbol -:> kindDoc, ExternData [Phantom])) 437 , (primSubName C.typeError "Quote", (kindType -:> kindDoc, ExternData [Phantom])) 438 , (primSubName C.typeError "QuoteLabel", (kindSymbol -:> kindDoc, ExternData [Phantom])) 439 , (primSubName C.typeError "Beside", (kindDoc -:> kindDoc -:> kindDoc, ExternData [Phantom, Phantom])) 440 , (primSubName C.typeError "Above", (kindDoc -:> kindDoc -:> kindDoc, ExternData [Phantom, Phantom])) 441 ] <> mconcat 442 [ primClass (primSubName C.typeError "Fail") (\kind -> kindDoc -:> kind) 443 , primClass (primSubName C.typeError "Warn") (\kind -> kindDoc -:> kind) 444 ] 445 446-- | The primitive class map. This just contains the `Partial` class. 447-- `Partial` is used as a kind of magic constraint for partial functions. 448primClasses :: M.Map (Qualified (ProperName 'ClassName)) TypeClassData 449primClasses = 450 M.fromList 451 [ (primName "Partial", makeTypeClassData [] [] [] [] True) 452 ] 453 454-- | This contains all of the type classes from all Prim modules. 455allPrimClasses :: M.Map (Qualified (ProperName 'ClassName)) TypeClassData 456allPrimClasses = M.unions 457 [ primClasses 458 , primCoerceClasses 459 , primRowClasses 460 , primRowListClasses 461 , primSymbolClasses 462 , primTypeErrorClasses 463 ] 464 465primCoerceClasses :: M.Map (Qualified (ProperName 'ClassName)) TypeClassData 466primCoerceClasses = 467 M.fromList 468 -- class Coercible (a :: k) (b :: k) 469 [ (primSubName C.moduleCoerce "Coercible", makeTypeClassData 470 [ ("a", Just (tyVar "k")) 471 , ("b", Just (tyVar "k")) 472 ] [] [] [] True) 473 ] 474 475primRowClasses :: M.Map (Qualified (ProperName 'ClassName)) TypeClassData 476primRowClasses = 477 M.fromList 478 -- class Union (left :: Row k) (right :: Row k) (union :: Row k) | left right -> union, right union -> left, union left -> right 479 [ (primSubName C.moduleRow "Union", makeTypeClassData 480 [ ("left", Just (kindRow (tyVar "k"))) 481 , ("right", Just (kindRow (tyVar "k"))) 482 , ("union", Just (kindRow (tyVar "k"))) 483 ] [] [] 484 [ FunctionalDependency [0, 1] [2] 485 , FunctionalDependency [1, 2] [0] 486 , FunctionalDependency [2, 0] [1] 487 ] True) 488 489 -- class Nub (original :: Row k) (nubbed :: Row k) | original -> nubbed 490 , (primSubName C.moduleRow "Nub", makeTypeClassData 491 [ ("original", Just (kindRow (tyVar "k"))) 492 , ("nubbed", Just (kindRow (tyVar "k"))) 493 ] [] [] 494 [ FunctionalDependency [0] [1] 495 ] True) 496 497 -- class Lacks (label :: Symbol) (row :: Row k) 498 , (primSubName C.moduleRow "Lacks", makeTypeClassData 499 [ ("label", Just kindSymbol) 500 , ("row", Just (kindRow (tyVar "k"))) 501 ] [] [] [] True) 502 503 -- class RowCons (label :: Symbol) (a :: k) (tail :: Row k) (row :: Row k) | label tail a -> row, label row -> tail a 504 , (primSubName C.moduleRow "Cons", makeTypeClassData 505 [ ("label", Just kindSymbol) 506 , ("a", Just (tyVar "k")) 507 , ("tail", Just (kindRow (tyVar "k"))) 508 , ("row", Just (kindRow (tyVar "k"))) 509 ] [] [] 510 [ FunctionalDependency [0, 1, 2] [3] 511 , FunctionalDependency [0, 3] [1, 2] 512 ] True) 513 ] 514 515primRowListClasses :: M.Map (Qualified (ProperName 'ClassName)) TypeClassData 516primRowListClasses = 517 M.fromList 518 -- class RowToList (row :: Row k) (list :: RowList k) | row -> list 519 [ (primSubName C.moduleRowList "RowToList", makeTypeClassData 520 [ ("row", Just (kindRow (tyVar "k"))) 521 , ("list", Just (kindRowList (tyVar "k"))) 522 ] [] [] 523 [ FunctionalDependency [0] [1] 524 ] True) 525 ] 526 527primSymbolClasses :: M.Map (Qualified (ProperName 'ClassName)) TypeClassData 528primSymbolClasses = 529 M.fromList 530 -- class Append (left :: Symbol) (right :: Symbol) (appended :: Symbol) | left right -> appended, right appended -> left, appended left -> right 531 [ (primSubName C.moduleSymbol "Append", makeTypeClassData 532 [ ("left", Just kindSymbol) 533 , ("right", Just kindSymbol) 534 , ("appended", Just kindSymbol) 535 ] [] [] 536 [ FunctionalDependency [0, 1] [2] 537 , FunctionalDependency [1, 2] [0] 538 , FunctionalDependency [2, 0] [1] 539 ] True) 540 541 -- class Compare (left :: Symbol) (right :: Symbol) (ordering :: Ordering) | left right -> ordering 542 , (primSubName C.moduleSymbol "Compare", makeTypeClassData 543 [ ("left", Just kindSymbol) 544 , ("right", Just kindSymbol) 545 , ("ordering", Just kindOrdering) 546 ] [] [] 547 [ FunctionalDependency [0, 1] [2] 548 ] True) 549 550 -- class Cons (head :: Symbol) (tail :: Symbol) (symbol :: Symbol) | head tail -> symbol, symbol -> head tail 551 , (primSubName C.moduleSymbol "Cons", makeTypeClassData 552 [ ("head", Just kindSymbol) 553 , ("tail", Just kindSymbol) 554 , ("symbol", Just kindSymbol) 555 ] [] [] 556 [ FunctionalDependency [0, 1] [2] 557 , FunctionalDependency [2] [0, 1] 558 ] True) 559 ] 560 561primTypeErrorClasses :: M.Map (Qualified (ProperName 'ClassName)) TypeClassData 562primTypeErrorClasses = 563 M.fromList 564 -- class Fail (message :: Symbol) 565 [ (primSubName C.typeError "Fail", makeTypeClassData 566 [("message", Just kindDoc)] [] [] [] True) 567 568 -- class Warn (message :: Symbol) 569 , (primSubName C.typeError "Warn", makeTypeClassData 570 [("message", Just kindDoc)] [] [] [] True) 571 ] 572 573-- | Finds information about data constructors from the current environment. 574lookupConstructor :: Environment -> Qualified (ProperName 'ConstructorName) -> (DataDeclType, ProperName 'TypeName, SourceType, [Ident]) 575lookupConstructor env ctor = 576 fromMaybe (internalError "Data constructor not found") $ ctor `M.lookup` dataConstructors env 577 578-- | Finds information about values from the current environment. 579lookupValue :: Environment -> Qualified Ident -> Maybe (SourceType, NameKind, NameVisibility) 580lookupValue env ident = ident `M.lookup` names env 581 582dictTypeName' :: Text -> Text 583dictTypeName' = (<> "$Dict") 584 585dictTypeName :: ProperName a -> ProperName a 586dictTypeName = ProperName . dictTypeName' . runProperName 587 588isDictTypeName :: ProperName a -> Bool 589isDictTypeName = T.isSuffixOf "$Dict" . runProperName 590 591-- | 592-- Given the kind of a type, generate a list @Nominal@ roles. This is used for 593-- opaque foreign types as well as type classes. 594nominalRolesForKind :: Type a -> [Role] 595nominalRolesForKind k = replicate (kindArity k) Nominal 596 597kindArity :: Type a -> Int 598kindArity = length . fst . unapplyKinds 599 600unapplyKinds :: Type a -> ([Type a], Type a) 601unapplyKinds = go [] where 602 go kinds (TypeApp _ (TypeApp _ fn k1) k2) 603 | eqType fn tyFunction = go (k1 : kinds) k2 604 go kinds (ForAll _ _ _ k _) = go kinds k 605 go kinds k = (reverse kinds, k) 606