Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
Synopsis
- type Constraint = Either (InfernoType, InfernoType, [TypeError SourcePos]) (Location SourcePos, TypeClass)
- data TypeError a
- = UnificationFail (Set TypeClass) InfernoType InfernoType (Location a)
- | ExpectedFunction (Set TypeClass) InfernoType InfernoType (Location a)
- | InfiniteType TV InfernoType (Location a)
- | UnboundNameInNamespace (Scoped ModuleName) (Either VCObjectHash Namespace) (Location a)
- | UnboundExtIdent (Scoped ModuleName) ExtIdent (Location a)
- | ImplicitVarTypeOverlap (Set TypeClass) ExtIdent InfernoType InfernoType (Location a)
- | VarMultipleOccurrence Ident (Location a) (Location a)
- | IfConditionMustBeBool (Set TypeClass) InfernoType (Location a)
- | AssertConditionMustBeBool (Set TypeClass) InfernoType (Location a)
- | IfBranchesMustBeEqType (Set TypeClass) InfernoType InfernoType (Location a) (Location a)
- | CaseBranchesMustBeEqType (Set TypeClass) InfernoType InfernoType (Location a) (Location a)
- | PatternUnificationFail InfernoType InfernoType (Pat (Pinned VCObjectHash) a) (Location a)
- | PatternsMustBeEqType (Set TypeClass) InfernoType InfernoType (Pat (Pinned VCObjectHash) a) (Pat (Pinned VCObjectHash) a) (Location a) (Location a)
- | TypeClassNotFoundError (Set TypeClass) TypeClass (Location a)
- | TypeClassNoPartialMatch TypeClass (Location a)
- | CouldNotFindTypeclassWitness (Set TypeClass) (Location a)
- | NonExhaustivePatternMatch Pattern (Location a)
- | UselessPattern (Maybe (Pat (Pinned VCObjectHash) a)) (Location a)
- | ModuleNameTaken ModuleName (Location a)
- | ModuleDoesNotExist ModuleName (Location a)
- | NameInModuleDoesNotExist ModuleName Ident (Location a)
- | AmbiguousName ModuleName Namespace (Location a)
- newtype Subst = Subst (Map TV InfernoType)
- inferExpr :: Map ModuleName (PinnedModule m) -> Expr (Pinned VCObjectHash) SourcePos -> Either [TypeError SourcePos] (Expr (Pinned VCObjectHash) SourcePos, TCScheme, Map (Location SourcePos) (TypeMetadata TCScheme))
- closeOver :: Set TypeClass -> ImplType -> TCScheme
- closeOverType :: InfernoType -> TCScheme
- findTypeClassWitnesses :: Set TypeClass -> Maybe Int -> Set TypeClass -> Set TV -> [Subst]
- inferTypeReps :: Set TypeClass -> TCScheme -> [InfernoType] -> InfernoType -> Either [TypeError SourcePos] [InfernoType]
- inferPossibleTypes :: Set TypeClass -> TCScheme -> [Maybe InfernoType] -> Maybe InfernoType -> Either [TypeError SourcePos] ([[InfernoType]], [InfernoType])
Documentation
type Constraint = Either (InfernoType, InfernoType, [TypeError SourcePos]) (Location SourcePos, TypeClass) Source #
Instances
inferExpr :: Map ModuleName (PinnedModule m) -> Expr (Pinned VCObjectHash) SourcePos -> Either [TypeError SourcePos] (Expr (Pinned VCObjectHash) SourcePos, TCScheme, Map (Location SourcePos) (TypeMetadata TCScheme)) Source #
Solve for the top level type of an expression in a given environment
closeOver :: Set TypeClass -> ImplType -> TCScheme Source #
Canonicalize and return the polymorphic toplevel type.
closeOverType :: InfernoType -> TCScheme Source #
findTypeClassWitnesses :: Set TypeClass -> Maybe Int -> Set TypeClass -> Set TV -> [Subst] Source #
This function encodes our typeclasses into CNF clauses for the SAT-solver.
The translation works in the following way:
Given a set of type-classes, e.g. `{requires addition on 'a int producing 'b ,requires addition on 'b 'b producing double}`
we first compute all the matching instances from allClasses
, in this case, we get:
`requires addition on 'a int producing b
matches:
- `requires addition on int int producing int`
- `requires addition on double int producing double`
`requires addition on 'b 'b producing double` matches:
- `requires addition on double double producing double`
Now we translate each possible class instantiation into the following clauses:
`requires addition on int int producing int` becomes:
`'a_int - add_class_1_inst_1_arg_1`
`'b_int - add_class_1_inst_1_arg_3`
`add_class_1_inst_1_arg_1 / add_class_1_inst_1_arg_3 - add_class_1_inst_1`
`requires addition on double int producing double` becomes:
`'a_double - add_class_1_inst_2_arg_1`
`'b_doube - add_class_1_inst_2_arg_3`
`add_class_1_inst_2_arg_1 / add_class_1_inst_2_arg_3 - add_class_1_inst_2`
We have to make sure that exactly one instance matches,
i.e. `requires addition on int int producing int` or `requires addition on double int producing double`, but not both:
`add_class_1_inst_1 XOR add_class_1_inst_2`
Next we encode the second set of matching instances, namely `requires addition on double double producing double`:
`'b_doube - add_class_2_inst_1_arg_1`
`'b_doube - add_class_2_inst_1_arg_2`
`add_class_2_inst_1_arg_1 / add_class_2_inst_1_arg_2 - add_class_2_inst_1`
Since the second typeclass only matches one instance, we simply add it in as true:
add_class_2_inst_1
Finally, we collect all the variables with all their possible types and encode the condition that exactly one type for each is matched:
`'a_int XOR a_double
`'b_int XOR b_double
If the SAT solver returns SAT, we simply check which one of `'a_?` and `'b_?` is set to true in the resulting model.
If the solver returns the model `'a_double b_double
and we want to check for any more solutions, we simply add `-('a_double 'b_double)`
(-
a_double / -b_double
in CNF) as a clause and re-run the solver. Once all assignments have been exhausted, we will get UNSAT.
inferTypeReps :: Set TypeClass -> TCScheme -> [InfernoType] -> InfernoType -> Either [TypeError SourcePos] [InfernoType] Source #
Given a type signature and some concrete assignment of types (assumes inputTys and outputTy have no free variables) | this function computes the runtime reps
inferPossibleTypes :: Set TypeClass -> TCScheme -> [Maybe InfernoType] -> Maybe InfernoType -> Either [TypeError SourcePos] ([[InfernoType]], [InfernoType]) Source #
Orphan instances
Substitutable Constraint Source # | |
apply :: Subst -> Constraint -> Constraint # ftv :: Constraint -> Set TV # |