on master help sign in
WIP: type inference

-non-compilation checkpoint

commita8da548dbfa3900ea6b356917614b1096cf77c2a authorAgentM <agentm@themactionfaction.com> dateThu 3 Mar 2016, 22:34 (11 years ago) parent5f34a12
10 files changed+102−30
ProjectM36/Atom.hs+2 ProjectM36/AtomType.hs+47−19 ProjectM36/Base.hs+1−1 ProjectM36/Client.hs+1−1 ProjectM36/DataTypes/Basic.hs+5−1 ProjectM36/Error.hs+1 ProjectM36/Relation.hs+22−1 ProjectM36/Relation/Show/Term.hs+22−6 ProjectM36/Tuple.hs+1 ProjectM36/TypeConstructorDef.hs−1
ProjectM36/Atom.hs+2
@@ -63,3 +63,5 @@ atomToText :: Atom -> T.Text
6363atomToText (Atom atom) = toText atom
6464atomToText (ConstructedAtom dConsName _ atoms) = dConsName `T.append` T.intercalate " " (map atomToText atoms)
6565
66+
67+
ProjectM36/AtomType.hs+47−19
@@ -1,7 +1,6 @@
11{-# LANGUAGE OverloadedStrings #-}
22module ProjectM36.AtomType where
33import ProjectM36.Base
4−import ProjectM36.Relation
54import ProjectM36.DataTypes.Primitive
65import qualified ProjectM36.TypeConstructorDef as TCD
76import qualified ProjectM36.TypeConstructor as TC
@@ -9,30 +8,14 @@ import qualified ProjectM36.DataConstructorDef as DCD
98import qualified Data.Text as T
109import ProjectM36.Error
1110import ProjectM36.Attribute
12−import ProjectM36.Atom
1311import qualified Data.Vector as V
1412import qualified Data.Set as S
1513import qualified Data.List as L
1614import Data.Maybe (isJust)
1715import Control.Monad.Writer
1816import qualified Data.Map as M
19−--import Debug.Trace
17+import Debug.Trace
2018
21−typesAsRelation :: TypeConstructorMapping -> Either RelationalError Relation
22−typesAsRelation types = mkRelationFromTuples attrs tuples
23− where
24− attrs = attributesFromList [Attribute "TypeConstructor" textAtomType,
25− Attribute "DataConstructors" dConsType]
26− subAttrs = attributesFromList [Attribute "DataConstructor" textAtomType]
27− dConsType = RelationAtomType subAttrs
28− tuples = map mkTypeConsDescription types
29−
30− mkTypeConsDescription (tCons, dConsList) = RelationTuple attrs (V.fromList [textAtom (TCD.name tCons), mkDataConsRelation dConsList])
31−
32− mkDataConsRelation dConsList = case mkRelationFromTuples subAttrs $ map (\dCons -> RelationTuple subAttrs (V.singleton $ textAtom $ T.intercalate " " ((DCD.name dCons):(map (T.pack . show) (DCD.fields dCons))))) dConsList of
33− Left err -> error ("mkRelationFromTuples pooped " ++ show err)
34− Right rel -> Atom rel
35−
3619findDataConstructor :: DataConstructorName -> TypeConstructorMapping -> Maybe (TypeConstructorDef, DataConstructorDef)
3720findDataConstructor dName tConsList = foldr tConsFolder Nothing tConsList
3821 where
@@ -89,6 +72,7 @@ atomTypeForDataConstructor tConss dConsName atomArgTypes = do
8972 Just (tCons, dCons) -> do
9073 --validate that the type constructor arguments are fulfilled in the data constructor
9174 typeVars <- resolveDataConstructorTypeVars dCons atomArgTypes tConss
75+ traceShowM typeVars
9276 pure (ConstructedAtomType (TCD.name tCons) typeVars)
9377
9478-- | Walks the data and type constructors to extract the type variable map.
@@ -96,6 +80,9 @@ resolveDataConstructorTypeVars :: DataConstructorDef -> [AtomType] -> TypeConstr
9680resolveDataConstructorTypeVars dCons aTypeArgs tConss = do
9781 maps <- mapM (\(dCons',aTypeArg) -> resolveDataConstructorArgTypeVars dCons' aTypeArg tConss) (zip (DCD.fields dCons) aTypeArgs)
9882 --if any two maps have the same key and different values- bail!
83+ let typeVarMapFolder
84+ foldr typeVarMapFolder (Right M.empty) maps
85+ --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.
9986 pure (M.unions maps)
10087
10188-- | Attempt to match the data constructor argument to a type constructor type variable.
@@ -147,6 +134,7 @@ dupes (x:y:xs) = dupes(x:[y]) ++ dupes(xs)
147134-- | Create an atom type iff all type variables are provided.
148135-- Either Int Text -> ConstructedAtomType "Either" {Int , Text}
149136atomTypeForTypeConstructor :: TypeConstructor -> TypeConstructorMapping -> Either RelationalError AtomType
137+atomTypeForTypeConstructor (PrimitiveTypeConstructor _ aType) _ = Right aType
150138atomTypeForTypeConstructor tCons tConss = case findTypeConstructor (TC.name tCons) tConss of
151139 Nothing -> Left (NoSuchTypeConstructorError (TC.name tCons))
152140 Just (tConsDef, _) -> do
@@ -166,4 +154,44 @@ findTypeConstructor name tConsList = foldr tConsFolder Nothing tConsList
166154 Just (tCons, dConsList)
167155 else
168156 accum
169−
157+
158+resolveAtomType :: AtomType -> AtomType -> Either RelationalError AtomType
159+resolveAtomType orig@(ConstructedAtomType dConsName resolvedTypeVarMap) (ConstructedAtomType _ unresolvedTypeVarMap) = do
160+ _ <- resolveAtomTypesInTypeVarMap resolvedTypeVarMap unresolvedTypeVarMap
161+ pure orig
162+resolveAtomType typeFromRelation unresolvedType = if typeFromRelation == unresolvedType then
163+ Right typeFromRelation
164+ else
165+ Left (AtomTypeMismatchError typeFromRelation unresolvedType)
166+
167+-- this could be optimized to reduce new tuple creation- if anyatomtype does not appear, just return the original typevarmap
168+resolveAtomTypesInTypeVarMap :: TypeVarMap -> TypeVarMap -> Either RelationalError TypeVarMap
169+resolveAtomTypesInTypeVarMap resolvedTypeMap unresolvedTypeMap = do
170+ let lookup key tMap = case M.lookup key tMap of
171+ Nothing -> Left (TypeConstructorTypeVarMissing key)
172+ Just val -> Right val
173+ let resolveTypePair unresKey AnyAtomType = do
174+ resType <- lookup unresKey resolvedTypeMap
175+ pure (unresKey, resType)
176+ resolveTypePair unresKey subType@(ConstructedAtomType _ _) = do --recurse
177+ resType <- lookup unresKey resolvedTypeMap
178+ resAType <- resolveAtomType resType subType
179+ pure (unresKey, resAType)
180+ resolveTypePair unresKey unresV = pure (unresKey, unresV)
181+ mapM_ (uncurry resolveTypePair) (M.toList unresolvedTypeMap)
182+ pure resolvedTypeMap
183+
184+-- | See notes at `resolveTypesInTuple`. The typeFromRelation must not include any wildcards.
185+resolveTypeInAtom :: AtomType -> Atom -> Either RelationalError Atom
186+resolveTypeInAtom typeFromRelation atomIn@(ConstructedAtom dConsName _ args) = do
187+ newType <- resolveAtomType typeFromRelation (atomTypeForAtom atomIn)
188+ pure (ConstructedAtom dConsName newType args)
189+resolveTypeInAtom _ atom = Right atom
190+
191+-- | 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.
192+-- 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.
193+resolveTypesInTuple :: Attributes -> RelationTuple -> Either RelationalError RelationTuple
194+resolveTypesInTuple resolvedAttrs (RelationTuple _ tupAtoms) = do
195+ newAtoms <- mapM (\(atom, resolvedType) -> resolveTypeInAtom resolvedType atom) (zip (V.toList tupAtoms) (map atomType (V.toList resolvedAttrs)))
196+ Right (RelationTuple resolvedAttrs (V.fromList newAtoms))
197+
ProjectM36/Base.hs+1−1
@@ -133,7 +133,7 @@ data AtomType = AtomType ConcreteTypeRep |
133133 RelationAtomType Attributes |
134134 ConstructedAtomType TypeConstructorName TypeVarMap |
135135 AnyAtomType
136− --wildcard used in Atom Functions
136+ --wildcard used in Atom Functions and tuples for data constructors which don't provide all arguments to the type constructor
137137 deriving (Eq,NFData,Generic,Binary,Show)
138138
139139type TypeVarMap = M.Map TypeVarName AtomType
ProjectM36/Client.hs+1−1
@@ -59,7 +59,7 @@ import ProjectM36.Attribute hiding (atomTypes)
5959import ProjectM36.Persist (DiskSync(..))
6060import ProjectM36.Notifications
6161import ProjectM36.Server.RemoteCallTypes
62−import ProjectM36.AtomType (typesAsRelation)
62+import ProjectM36.Relation (typesAsRelation)
6363import Network.Transport.TCP (createTransport, defaultTCPParameters, encodeEndPointAddress)
6464import Control.Distributed.Process.Node (newLocalNode, initRemoteTable, runProcess, LocalNode, forkProcess)
6565import Control.Distributed.Process.Extras.Internal.Types (whereisRemote)
ProjectM36/DataTypes/Basic.hs+5−1
@@ -8,7 +8,11 @@ basicTypeConstructorMapping :: TypeConstructorMapping
88basicTypeConstructorMapping = primitiveTypeConstructorMapping ++ moreTypes
99 where
1010 moreTypes = [(ADTypeConstructorDef "Day" ["a"],
11− [DataConstructorDef "Day" [DataConstructorDefTypeConstructorArg (PrimitiveTypeConstructor "Int" intAtomType)]])]
11+ [DataConstructorDef "Day" [DataConstructorDefTypeConstructorArg (PrimitiveTypeConstructor "Int" intAtomType)]]),
12+ (ADTypeConstructorDef "Maybe" ["a"],
13+ [DataConstructorDef "Nothing" [],
14+ DataConstructorDef "Just" [DataConstructorDefTypeVarNameArg "a"]])
15+ ]
1216
1317
1418
ProjectM36/Error.hs+1
@@ -41,6 +41,7 @@ data RelationalError = NoSuchAttributeNamesError (S.Set AttributeName)
4141 | DataConstructorNameInUseError DataConstructorName
4242 | DataConstructorUsesUndeclaredTypeVariable TypeVarName
4343 | TypeConstructorTypeVarsMismatch (S.Set TypeVarName) (S.Set TypeVarName)
44+ | TypeConstructorTypeVarMissing TypeVarName
4445 | AtomTypeNameInUseError AtomTypeName
4546 | IncompletelyDefinedAtomTypeWithConstructorError
4647 | AtomTypeNameNotInUseError AtomTypeName
ProjectM36/Relation.hs+22−1
@@ -4,14 +4,20 @@ import qualified Data.Set as S
44import qualified Data.HashSet as HS
55import Control.Monad
66import qualified Data.Vector as V
7+import ProjectM36.Atom
78import ProjectM36.Base
89import ProjectM36.Tuple
10+import ProjectM36.DataTypes.Primitive
911import qualified ProjectM36.Attribute as A
1012import qualified ProjectM36.AttributeNames as AS
1113import ProjectM36.TupleSet
1214import ProjectM36.Error
1315import qualified Control.Parallel.Strategies as P
16+import qualified ProjectM36.TypeConstructorDef as TCD
17+import qualified ProjectM36.DataConstructorDef as DCD
18+import qualified Data.Text as T
1419import Data.Either (isRight)
20+import Debug.Trace
1521
1622attributes :: Relation -> Attributes
1723attributes (Relation attrs _ ) = attrs
@@ -71,7 +77,7 @@ singletonTuple rel@(Relation _ tupleSet) = if cardinality rel == Finite 1 then
7177union :: Relation -> Relation -> Either RelationalError Relation
7278union (Relation attrs1 tupSet1) (Relation attrs2 tupSet2) =
7379 if not (A.attributesEqual attrs1 attrs2)
74− then Left $ AttributeNamesMismatchError (A.attributeNameSet (A.attributesDifference attrs1 attrs2))
80+ then Left $ AttributeNamesMismatchError (A.attributeNameSet (A.attributesDifference (traceShowId attrs1) (traceShowId attrs2)))
7581 else
7682 Right $ Relation attrs1 newtuples
7783 where
@@ -257,5 +263,20 @@ imageRelationJoin rel1@(Relation attrNameSet1 tupSet1) rel2@(Relation attrNameSe
257263 tupleSetJoiner tup1 acc = undefined
258264-}
259265
266+typesAsRelation :: TypeConstructorMapping -> Either RelationalError Relation
267+typesAsRelation types = mkRelationFromTuples attrs tuples
268+ where
269+ attrs = A.attributesFromList [Attribute "TypeConstructor" textAtomType,
270+ Attribute "DataConstructors" dConsType]
271+ subAttrs = A.attributesFromList [Attribute "DataConstructor" textAtomType]
272+ dConsType = RelationAtomType subAttrs
273+ tuples = map mkTypeConsDescription types
274+
275+ mkTypeConsDescription (tCons, dConsList) = RelationTuple attrs (V.fromList [textAtom (TCD.name tCons), mkDataConsRelation dConsList])
276+
277+ mkDataConsRelation dConsList = case mkRelationFromTuples subAttrs $ map (\dCons -> RelationTuple subAttrs (V.singleton $ textAtom $ T.intercalate " " ((DCD.name dCons):(map (T.pack . show) (DCD.fields dCons))))) dConsList of
278+ Left err -> error ("mkRelationFromTuples pooped " ++ show err)
279+ Right rel -> Atom rel
280+
260281
261282
ProjectM36/Relation/Show/Term.hs+22−6
@@ -4,10 +4,13 @@ module ProjectM36.Relation.Show.Term where
44import ProjectM36.Base
55import ProjectM36.Tuple
66import ProjectM36.Relation
7−import qualified Data.Set as S
7+import ProjectM36.Attribute
8+import ProjectM36.ConcreteTypeRep
89import qualified Data.List as L
910import qualified Data.Text as T
10−import Data.Typeable (cast)
11+import qualified Data.Vector as V
12+import qualified Data.Map as M
13+import Data.Typeable (cast, tyConName, splitTyConApp)
1114
1215boxV :: StringType
1316boxV = "│"
@@ -78,18 +81,28 @@ cellSizes (header, body) = map (\row -> (map maxRowWidth row, map (length . brea
7881 L.maximumBy compare (lengths row)
7982 lengths row = map T.length (breakLines row)
8083 allRows = [header] ++ body
84+
85+attributeAsCell :: Attribute -> Cell
86+attributeAsCell attr = attributeName attr `T.append` "::" `T.append` prettyAtomType (atomType attr)
87+
88+prettyAtomType :: AtomType -> T.Text
89+prettyAtomType (AtomType primitiveType) = T.pack (tyConName (fst (splitTyConApp (unCTR primitiveType))))
90+prettyAtomType (RelationAtomType attrs) = "relation {" `T.append` T.intercalate "," (map attributeAsCell (V.toList attrs)) `T.append` "}"
91+prettyAtomType (ConstructedAtomType tConsName typeVarMap) = tConsName `T.append` " " `T.append` T.pack (show (M.toList typeVarMap)) -- 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?)
92+prettyAtomType AnyAtomType = "?AnyAtomType?"
8193
8294relationAsTable :: Relation -> Table
8395relationAsTable rel@(Relation _ tupleSet) = (header, body)
8496 where
85− oAttrs = orderedAttributeNames rel
86− header = oAttrs
97+ oAttrs = orderedAttributes rel
98+ oAttrNames = orderedAttributeNames rel
99+ header = map attributeAsCell oAttrs
87100 body :: [[Cell]]
88101 body = L.foldl' tupleFolder [] (asList tupleSet)
89102 tupleFolder acc tuple = acc ++ [map (\attrName -> case atomForAttributeName attrName tuple of
90103 Left _ -> "?"
91104 Right atom -> showAtom atom
92− ) oAttrs]
105+ ) oAttrNames]
93106
94107showAtom :: Atom -> StringType
95108showAtom (Atom atom) = case cast atom of
@@ -135,8 +148,11 @@ renderBody cellMatrix cellLocs = renderRows `T.append` renderBottomBar
135148 rowHeightMatrix = zip cellMatrix (tail rowLocations)
136149 renderBottomBar = renderHBar boxBL boxBB boxBR columnLocations
137150
151+orderedAttributes :: Relation -> [Attribute]
152+orderedAttributes rel = L.sortBy (\a b -> attributeName a `compare` attributeName b) (V.toList (attributes rel))
153+
138154orderedAttributeNames :: Relation -> [AttributeName]
139−orderedAttributeNames = S.toAscList . attributeNames
155+orderedAttributeNames rel = map attributeName (orderedAttributes rel)
140156
141157repeatString :: Int -> StringType -> StringType
142158repeatString c s = T.concat (take c (repeat s))
ProjectM36/Tuple.hs+1
@@ -200,3 +200,4 @@ reorderTuple attrs tupIn = if tupleAttributes tupIn == attrs then
200200 mapper attr = case atomForAttributeName (attributeName attr) tupIn of
201201 Left _ -> undefined
202202 Right atom -> atom
203+
ProjectM36/TypeConstructorDef.hs−1
@@ -1,6 +1,5 @@
11module ProjectM36.TypeConstructorDef where
22import ProjectM36.Base
3−import qualified Data.Set as S
43
54name :: TypeConstructorDef -> TypeConstructorName
65name (ADTypeConstructorDef nam _) = nam