@@ -3,6 +3,7 @@ module Type.Unify (unify) where
3import Type.Type
3import Type.Type
4import qualified Data.UnionFind.IO as UF
4import qualified Data.UnionFind.IO as UF
5import qualified Data.Map as Map
5import qualified Data.Map as Map
6+import qualified Data.Maybe as Maybe
6import qualified Type.State as TS
7import qualified Type.State as TS
7import Control.Arrow (first,second)
8import Control.Arrow (first,second)
8import Control.Monad.State
9import Control.Monad.State
@@ -78,25 +79,26 @@ actuallyUnify span variable1 variable2 = do
79 unifyNumber svar name
80 unifyNumber svar name
80 | name `elem` ["Int","Float","number"] = flexAndUnify svar
81 | name `elem` ["Int","Float","number"] = flexAndUnify svar
81− | otherwise = TS.addError span "Expecting a number (Int or Float)" variable1 variable2
82+ | otherwise = TS.addError span (Just hint) variable1 variable2
83+ where hint = "A number must be an Int or Float"
85+ comparableError maybe =
83− comparableError str = TS.addError span (str ++ msg) variable1 variable2
86+ TS.addError span (Just $ Maybe.fromMaybe msg maybe) variable1 variable2
84− where msg = "Expecting something comparable such as an\n" ++
85− "Int, Float, Char, String, or a list or tuple of comparables."
87+ where msg = "A comparable must be an Int, Float, Char, String, list, or tuple"
87 unifyComparable var name
89 unifyComparable var name
88 | name `elem` ["Int","Float","Char","String","comparable"] = flexAndUnify var
90 | name `elem` ["Int","Float","Char","String","comparable"] = flexAndUnify var
89− | otherwise = comparableError ""
91+ | otherwise = comparableError Nothing
91 unifyComparableStructure varSuper varFlex =
93 unifyComparableStructure varSuper varFlex =
92 do struct <- liftIO $ collectApps varFlex
94 do struct <- liftIO $ collectApps varFlex
93 case struct of
95 case struct of
94− Other -> comparableError ""
96+ Other -> comparableError Nothing
95 List v -> do flexAndUnify varSuper
97 List v -> do flexAndUnify varSuper
96 unify' v =<< liftIO (var $ Is Comparable)
98 unify' v =<< liftIO (var $ Is Comparable)
98 | length vs > 6 ->
100 | length vs > 6 ->
99− comparableError "Cannot compare a tuple with more than 6 elements.\n"
101+ comparableError $ Just "Cannot compare a tuple with more than 6 elements"
100 | otherwise ->
102 | otherwise ->
101 do flexAndUnify varSuper
103 do flexAndUnify varSuper
102 cmpVars <- liftIO $ forM [1..length vs] $ \_ -> var (Is Comparable)
104 cmpVars <- liftIO $ forM [1..length vs] $ \_ -> var (Is Comparable)
@@ -106,13 +108,12 @@ actuallyUnify span variable1 variable2 = do
106 do struct <- liftIO $ collectApps varFlex
108 do struct <- liftIO $ collectApps varFlex
107 case struct of
109 case struct of
108 List _ -> flexAndUnify varSuper
110 List _ -> flexAndUnify varSuper
109− _ -> comparableError ""
111+ _ -> comparableError Nothing
111− rigidError variable = TS.addError span msg variable1 variable2
113+ rigidError variable = TS.addError span (Just hint) variable1 variable2
112− where
114+ where hint = "There is a problem with the '" ++
114− [ "Cannot unify rigid type variable '", render (pretty Never variable), "'.\n"
115+ render (pretty Never variable) ++
115− , "It is likely that a type annotation is not general enough." ]
116+ "' in the type signature. It currently is not possible to unify type variables that appear in top-level declarations and again in subexpressions"
117 superUnify =
118 superUnify =
118 case (flex desc1, flex desc2, name desc1, name desc2) of
119 case (flex desc1, flex desc2, name desc1, name desc2) of
@@ -138,7 +139,7 @@ actuallyUnify span variable1 variable2 = do
139 (Rigid, _, _, _) -> rigidError variable1
140 (Rigid, _, _, _) -> rigidError variable1
140 (_, Rigid, _, _) -> rigidError variable2
141 (_, Rigid, _, _) -> rigidError variable2
141− _ -> TS.addError span "" variable1 variable2
142+ _ -> TS.addError span Nothing variable1 variable2
143 case (structure desc1, structure desc2) of
144 case (structure desc1, structure desc2) of
144 (Nothing, Nothing) | flex desc1 == Flexible && flex desc1 == Flexible -> merge
145 (Nothing, Nothing) | flex desc1 == Flexible && flex desc1 == Flexible -> merge
@@ -193,5 +194,5 @@ actuallyUnify span variable1 variable2 = do
193 eat (x:xs) (y:ys) = eat xs ys
194 eat (x:xs) (y:ys) = eat xs ys
194 eat xs ys = xs
195 eat xs ys = xs
196− _ -> TS.addError span "" variable1 variable2
197+ _ -> TS.addError span Nothing variable1 variable2