@@ -15,7 +15,6 @@ import Data.Either (rights)
1515import Control.Monad.Writer
1616import qualified Data.Map as M
1717import qualified Data.Text as T
18−--import Debug.Trace
1918
2019findDataConstructor :: DataConstructorName -> TypeConstructorMapping -> Maybe (TypeConstructorDef, DataConstructorDef)
2120findDataConstructor dName tConsList = foldr tConsFolder Nothing tConsList
@@ -89,7 +88,7 @@ resolveDataConstructorTypeVars dCons aTypeArgs tConss = do
8988 case foldr typeVarMapFolder (Right M.empty) maps of
9089 Left err -> Left err
9190 Right typeVarMaps -> pure typeVarMaps
92− --if the data constructor cannot complete a type constructor variables (ex. "Nothing" could be Maybe Int or Maybe Text, etc.), then fill that space with AnyAtomType which is resolved when the relation is constructed- the relation must contain all resolved atom types.
91+ --if the data constructor cannot complete a type constructor variables (ex. "Nothing" could be Maybe Int or Maybe Text, etc.), then fill that space with TypeVar which is resolved when the relation is constructed- the relation must contain all resolved atom types.
9392
9493
9594-- | Attempt to match the data constructor argument to a type constructor type variable.
@@ -198,7 +197,7 @@ resolveTypeInAtom typeFromRelation atomIn@(ConstructedAtom dConsName _ args) = d
198197 pure (ConstructedAtom dConsName newType args)
199198resolveTypeInAtom _ atom = Right atom
200199
201−-- | When creating a tuple, the data constructor may not complete the type constructor arguments, so the wildcard "AnyAtomType" fills in the type constructor's argument. The tuple type must be resolved before it can be part of a relation, however.
200+-- | When creating a tuple, the data constructor may not complete the type constructor arguments, so the wildcard "TypeVar x" fills in the type constructor's argument. The tuple type must be resolved before it can be part of a relation, however.
202201-- Example: "Nothing" does not specify the the argument in "Maybe a", so allow delayed resolution in the tuple before it is added to the relation. Note that this resolution could cause a type error. Hardly a Hindley-Milner system.
203202resolveTypesInTuple :: Attributes -> RelationTuple -> Either RelationalError RelationTuple
204203resolveTypesInTuple resolvedAttrs (RelationTuple _ tupAtoms) = do
@@ -224,10 +223,10 @@ validateAtomType _ _ = Right ()
224223validateTuple :: RelationTuple -> TypeConstructorMapping -> Either RelationalError ()
225224validateTuple (RelationTuple _ atoms) tConss = mapM_ (\a -> validateAtomType (atomTypeForAtom a) tConss) atoms
226225
227−-- | Determine if two types are equal or compatible (including special handling for AnyAtomType).
226+-- | Determine if two types are equal or compatible (including special handling for TypeVar x).
228227atomTypeVerify :: AtomType -> AtomType -> Either RelationalError AtomType
229−atomTypeVerify AnyAtomType x = Right x
230−atomTypeVerify x AnyAtomType = Right x
228+atomTypeVerify (TypeVar _) x = Right x
229+atomTypeVerify x (TypeVar _) = Right x
231230atomTypeVerify x@(ConstructedAtomType tConsNameA tVarMapA) (ConstructedAtomType tConsNameB tVarMapB) =
232231 if tConsNameA /= tConsNameB then
233232 Left (TypeConstructorNameMismatch tConsNameA tConsNameB)
@@ -258,10 +257,30 @@ prettyAtomType (ConstructedAtomType tConsName typeVarMap) = tConsName `T.append`
258257 where
259258 showTypeVars (tyVarName, aType) = " (" `T.append` tyVarName `T.append` "::" `T.append` prettyAtomType aType `T.append` ")"
260259-- it would be nice to have the original ordering, but we don't have access to the type constructor here- maybe the typevarmap should be also positional (ordered map?)
261−prettyAtomType AnyAtomType = "?AnyAtomType?"
260+prettyAtomType (TypeVar x) = "?TypeVar " <> x <> "?"
262261prettyAtomType aType = T.take (T.length fullName - T.length "AtomType") fullName
263262 where fullName = (T.pack . show) aType
264263
265264prettyAttribute :: Attribute -> T.Text
266265prettyAttribute attr = A.attributeName attr `T.append` "::" `T.append` prettyAtomType (A.atomType attr)
267266
267+resolveTypeVariables :: [AtomType] -> [AtomType] -> TypeVarMap
268+resolveTypeVariables expectedArgTypes actualArgTypes = let tvmaps = map (uncurry resolveTypeVariable) (zip expectedArgTypes actualArgTypes) in
269+ M.unions tvmaps
270+
271+resolveTypeVariable :: AtomType -> AtomType -> TypeVarMap
272+resolveTypeVariable (TypeVar tv) typ = M.singleton tv typ
273+resolveTypeVariable (ConstructedAtomType _ _) (ConstructedAtomType _ actualTvMap) = actualTvMap
274+resolveTypeVariable _ _ = M.empty
275+
276+resolveFunctionReturnValue :: AtomFunctionName -> TypeVarMap -> AtomType -> Either RelationalError AtomType
277+resolveFunctionReturnValue funcName tvMap (ConstructedAtomType tCons retMap) = do
278+ let diff = M.difference retMap tvMap
279+ if M.null diff then
280+ pure (ConstructedAtomType tCons (M.intersection tvMap retMap))
281+ else
282+ Left (AtomFunctionTypeVariableResolutionError funcName (fst (head (M.toList diff))))
283+resolveFunctionReturnValue funcName tvMap (TypeVar tvName) = case M.lookup tvName tvMap of
284+ Nothing -> Left (AtomFunctionTypeVariableResolutionError funcName tvName)
285+ Just typ -> pure typ
286+resolveFunctionReturnValue _ _ typ = pure typ