1module Type.Unify (unify) where
4import qualified Data.UnionFind.IO as UF
5import qualified Type.State as TS
6import Control.Arrow (first,second)
7import Control.Monad.State
8import qualified Text.PrettyPrint as P
10unify :: Variable -> Variable -> StateT TS.SolverState IO ()
11unify variable1 variable2 = do
12 equivalent <- liftIO $ UF.equivalent variable1 variable2
13 if equivalent then return ()
14 else actuallyUnify variable1 variable2
16actuallyUnify :: Variable -> Variable -> StateT TS.SolverState IO ()
17actuallyUnify variable1 variable2 = do
18 desc1 <- liftIO $ UF.descriptor variable1
19 desc2 <- liftIO $ UF.descriptor variable2
20 let name' :: Maybe String
21 name' = case (name desc1, name desc2) of
22 (Just name1, Just name2) ->
23 case (flex desc1, flex desc2) of
24 (_, Flexible) -> Just name1
25 (Flexible, _) -> Just name2
26 (Is Number, Is _) -> Just name1
27 (Is _, Is Number) -> Just name2
28 (Is _, Is _) -> Just name1
30 (Just name1, _) -> Just name1
31 (_, Just name2) -> Just name2
35 flex' = case (flex desc1, flex desc2) of
38 (Is Number, Is _) -> Is Number
39 (Is _, Is Number) -> Is Number
40 (Is super, Is _) -> Is super
44 rank' = min (rank desc1) (rank desc2)
46 merge1 :: StateT TS.SolverState IO ()
48 if rank desc1 < rank desc2 then UF.union variable2 variable1
49 else UF.union variable1 variable2
50 UF.modifyDescriptor variable1 $ \desc ->
51 desc { structure = structure desc1, flex = flex', name = name' }
53 merge2 :: StateT TS.SolverState IO ()
55 if rank desc1 < rank desc2 then UF.union variable2 variable1
56 else UF.union variable1 variable2
57 UF.modifyDescriptor variable2 $ \desc ->
58 desc { structure = structure desc2, flex = flex', name = name' }
60 merge = if rank desc1 < rank desc2 then merge1 else merge2
62 fresh :: Maybe (Term1 Variable) -> StateT TS.SolverState IO Variable
64 var <- liftIO . UF.fresh $ Descriptor {
65 structure = structure, rank = rank', flex = flex',
66 name = name', copy = Nothing, mark = noMark
71 liftIO $ UF.modifyDescriptor var $ \desc -> desc { flex = Flexible }
72 unify variable1 variable2
75 case (flex desc1, flex desc2, name desc1, name desc2) of
76 (Is super1, Is super2, _, _)
77 | super1 == super2 -> merge
78 (Is Number, Is Comparable, _, _) -> merge1
79 (Is Comparable, Is Number, _, _) -> merge2
81 (Is Number, _, _, Just name)
82 | name `elem` ["Int","Float"] -> flexAndUnify variable1
83 | otherwise -> TS.addError "Expecting a number (Int or Float)" variable1 variable2
85 (_, Is Number, Just name, _)
86 | name `elem` ["Int","Float"] -> flexAndUnify variable2
87 | otherwise -> TS.addError "Expecting a number (Int or Float)" variable1 variable2
89 (Is Comparable, _, _, Just name)
90 | name `elem` ["Int","Float","Char"] -> flexAndUnify variable1
91 | otherwise -> TS.addError "Expecting something comparable (Int, Float, Char, [comparable])." variable1 variable2
93 (_, Is Comparable, Just name, _)
94 | name `elem` ["Int","Float","Char"] -> flexAndUnify variable2
95 | otherwise -> TS.addError "Expecting something comparable (Int, Float, Char, [comparable])." variable1 variable2
97 _ -> TS.addError "The following types are not equal" variable1 variable2
99 case (structure desc1, structure desc2) of
100 (Nothing, Nothing) | flex desc1 == Flexible && flex desc1 == Flexible -> merge
101 (Nothing, _) | flex desc1 == Flexible -> merge2
102 (_, Nothing) | flex desc2 == Flexible -> merge1
104 (Just (Var1 v), _) -> unify v variable2
105 (_, Just (Var1 v)) -> unify v variable1
107 (Nothing, _) -> superUnify
108 (_, Nothing) -> superUnify
110 (Just type1, Just type2) ->
111 case (type1,type2) of
112 (App1 term1 term2, App1 term1' term2') ->
116 (Fun1 term1 term2, Fun1 term1' term2') ->
121 (EmptyRecord1, EmptyRecord1) ->
124 (Record1 fields1 ext1, Record1 fields2 ext2) ->
125 TS.addError "did not write record unification yet" variable1 variable2
127 _ -> TS.addError "could not unify types" variable1 variable2
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list