~ubuntu-branches/ubuntu/wily/agda/wily-proposed

« back to all changes in this revision

Viewing changes to src/full/Agda/TypeChecking/Rules/LHS/Unify.hs

  • Committer: Package Import Robot
  • Author(s): Iain Lane, d5cf60f
  • Date: 2015-05-20 13:08:33 UTC
  • mfrom: (1.1.7)
  • Revision ID: package-import@ubuntu.com-20150520130833-cdcmhagwsouna237
Tags: 2.4.2.2-2
[d5cf60f] Depend on ${shlibs:Depends}, to get libc (& maybe other) deps

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
{-# LANGUAGE CPP #-}
2
 
{-# LANGUAGE DeriveDataTypeable #-}
3
 
{-# LANGUAGE DeriveFoldable #-}
4
 
{-# LANGUAGE DeriveFunctor #-}
5
 
{-# LANGUAGE DeriveTraversable #-}
6
 
{-# LANGUAGE FlexibleInstances #-}
 
1
{-# LANGUAGE CPP                        #-}
 
2
{-# LANGUAGE DeriveDataTypeable         #-}
 
3
{-# LANGUAGE DeriveFoldable             #-}
 
4
{-# LANGUAGE DeriveFunctor              #-}
 
5
{-# LANGUAGE DeriveTraversable          #-}
 
6
{-# LANGUAGE FlexibleInstances          #-}
7
7
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
8
 
{-# LANGUAGE MultiParamTypeClasses #-}
9
 
{-# LANGUAGE PatternGuards #-}
10
 
{-# LANGUAGE TupleSections #-}
11
 
{-# LANGUAGE TypeSynonymInstances #-}
 
8
{-# LANGUAGE MultiParamTypeClasses      #-}
 
9
{-# LANGUAGE PatternGuards              #-}
 
10
{-# LANGUAGE TupleSections              #-}
 
11
{-# LANGUAGE TypeSynonymInstances       #-}
12
12
 
13
13
module Agda.TypeChecking.Rules.LHS.Unify where
14
14
 
 
15
import Prelude hiding (null)
 
16
 
15
17
import Control.Arrow ((***))
16
18
import Control.Applicative hiding (empty)
17
19
import Control.Monad.State
18
20
import Control.Monad.Reader
19
 
import Control.Monad.Error
20
21
import Control.Monad.Writer (WriterT(..), MonadWriter(..), Monoid(..))
21
22
 
 
23
import Data.IntMap (IntMap)
 
24
import qualified Data.IntMap as IntMap
22
25
import Data.Map (Map)
23
26
import qualified Data.Map as Map
24
 
import Data.List hiding (sort)
 
27
import Data.List hiding (null, sort)
25
28
 
26
29
import Data.Typeable (Typeable)
27
30
import Data.Foldable (Foldable)
30
33
import Agda.Interaction.Options (optInjectiveTypeConstructors)
31
34
 
32
35
import Agda.Syntax.Common
33
 
import Agda.Syntax.Internal as I
 
36
import Agda.Syntax.Internal as I hiding (Substitution)
34
37
import Agda.Syntax.Literal
35
38
import Agda.Syntax.Position
36
39
 
42
45
import Agda.TypeChecking.DropArgs
43
46
import Agda.TypeChecking.Level (reallyUnLevelView)
44
47
import Agda.TypeChecking.Reduce
45
 
import Agda.TypeChecking.Pretty
 
48
import Agda.TypeChecking.Pretty hiding (empty)
 
49
import qualified Agda.TypeChecking.Pretty as P
46
50
import Agda.TypeChecking.Substitute hiding (Substitution)
47
51
import qualified Agda.TypeChecking.Substitute as S
48
52
import Agda.TypeChecking.Telescope
55
59
import Agda.TypeChecking.Rules.LHS.Problem
56
60
-- import Agda.TypeChecking.SyntacticEquality
57
61
 
 
62
import Agda.Utils.Except
 
63
  ( Error(noMsg, strMsg)
 
64
  , MonadError(catchError, throwError)
 
65
  )
 
66
 
58
67
import Agda.Utils.Maybe
 
68
import Agda.Utils.Monad
 
69
import Agda.Utils.Null
59
70
import Agda.Utils.Size
60
 
import Agda.Utils.Monad
61
71
 
62
 
#include "../../../undefined.h"
 
72
#include "undefined.h"
63
73
import Agda.Utils.Impossible
64
74
 
65
75
newtype Unify a = U { unUnify :: ReaderT UnifyEnv (WriterT UnifyOutput (ExceptionT UnifyException (StateT UnifyState TCM))) a }
79
89
instance HasConstInfo Unify where
80
90
  getConstInfo = U . lift . lift . lift . lift . getConstInfo
81
91
 
 
92
-- UnifyEnv
 
93
------------------------------------------------------------------------
 
94
 
82
95
data UnifyMayPostpone = MayPostpone | MayNotPostpone
83
96
 
84
97
type UnifyEnv = UnifyMayPostpone
85
 
emptyUEnv   = MayPostpone
 
98
 
 
99
emptyUEnv :: UnifyEnv
 
100
emptyUEnv = MayPostpone
86
101
 
87
102
noPostponing :: Unify a -> Unify a
88
 
noPostponing (U (ReaderT f)) = U . ReaderT . const $ f MayNotPostpone
 
103
noPostponing = U . local (const MayNotPostpone) . unUnify
89
104
 
90
105
askPostpone :: Unify UnifyMayPostpone
91
 
askPostpone = U . ReaderT $ return
 
106
askPostpone = U $ ask
92
107
 
93
108
-- | Output the result of unification (success or maybe).
94
109
type UnifyOutput = Unifiable
95
110
 
96
 
emptyUOutput :: UnifyOutput
97
 
emptyUOutput = mempty
98
 
 
99
111
-- | Were two terms unifiable or did we have to postpone some equation such that we are not sure?
100
112
data Unifiable
101
113
  = Definitely  -- ^ Unification succeeded.
121
133
    Possibly ->   e
122
134
 
123
135
data Equality = Equal TypeHH Term Term
124
 
type Sub = Map Nat Term
 
136
type Sub = IntMap Term
125
137
 
126
138
data UnifyException
127
139
  = ConstructorMismatch Type Term Term
134
146
  noMsg  = strMsg ""
135
147
  strMsg = GenericUnifyException
136
148
 
137
 
data UnifyState = USt { uniSub    :: Sub
138
 
                      , uniConstr :: [Equality]
139
 
                      }
 
149
data UnifyState = USt
 
150
  { uniSub    :: Sub
 
151
  , uniConstr :: [Equality]
 
152
  }
140
153
 
141
 
emptyUState = USt Map.empty []
 
154
emptyUState :: UnifyState
 
155
emptyUState = USt IntMap.empty []
142
156
 
143
157
-- | Throw-away error message.
144
158
projectionMismatch :: QName -> QName -> Unify a
156
170
  applySubst rho (Equal a s t) =
157
171
    Equal (applySubst rho a) (applySubst rho s) (applySubst rho t)
158
172
 
159
 
onSub :: (Sub -> a) -> Unify a
160
 
onSub f = U $ gets $ f . uniSub
 
173
getSub :: Unify Sub
 
174
getSub = U $ gets uniSub
161
175
 
162
176
modSub :: (Sub -> Sub) -> Unify ()
163
177
modSub f = U $ modify $ \s -> s { uniSub = f $ uniSub s }
246
260
i |-> (u, a) = do
247
261
  occursCheck i u a
248
262
  liftTCM $ reportSDoc "tc.lhs.unify.assign" 15 $ prettyTCM (var i) <+> text ":=" <+> prettyTCM u
249
 
  modSub $ Map.insert i (killRange u)
 
263
  modSub $ IntMap.insert i (killRange u)
250
264
  -- Apply substitution to itself (issue 552)
251
 
  rho  <- onSub id
 
265
  rho  <- getSub
252
266
  rho' <- traverse ureduce rho
253
267
  modSub $ const rho'
254
268
 
255
269
makeSubstitution :: Sub -> S.Substitution
256
270
makeSubstitution sub
257
 
  | Map.null sub = idS
258
 
  | otherwise    = map val [0 .. highestIndex] ++# raiseS (highestIndex + 1)
 
271
  | null sub  = idS
 
272
  | otherwise = map val [0 .. highestIndex] ++# raiseS (highestIndex + 1)
259
273
  where
260
 
    highestIndex = fst $ Map.findMax sub
261
 
    val i = maybe (var i) id $ Map.lookup i sub
 
274
    highestIndex = fst $ IntMap.findMax sub
 
275
    val i = fromMaybe (var i) $ IntMap.lookup i sub
262
276
 
263
277
-- | Apply the current substitution on a term and reduce to weak head normal form.
264
278
class UReduce t where
266
280
 
267
281
instance UReduce Term where
268
282
  ureduce u = doEtaContractImplicit $ do
269
 
    rho <- onSub makeSubstitution
 
283
    rho <- makeSubstitution <$> getSub
270
284
-- Andreas, 2013-10-24 the following call to 'normalise' is problematic
271
285
-- (see issue 924).  Instead, we only normalize if unifyAtomHH is undecided.
272
286
--    liftTCM $ etaContract =<< normalise (applySubst rho u)
329
343
    instantiate :: Nat -> Substitution -> Substitution
330
344
    instantiate i s = map (fmap $ inst i u) s
331
345
      where
332
 
        Just u = s !! i
 
346
        Just u = s !! i
333
347
 
 
348
    -- @inst i u v@ replaces index @i@ in @v@ by @u@, without removing the index.
334
349
    inst :: Nat -> Term -> Term -> Term
335
350
    inst i u v = applySubst us v
336
351
      where us = [var j | j <- [0..i - 1] ] ++# u :# raiseS (i + 1)
337
352
 
338
 
data UnificationResult = Unifies Substitution | NoUnify Type Term Term | DontKnow TCErr
 
353
data UnificationResult
 
354
  = Unifies Substitution
 
355
  | NoUnify Type Term Term
 
356
  | DontKnow TCErr
339
357
 
340
358
-- | Are we in a homogeneous (one type) or heterogeneous (two types) situation?
341
359
data HomHet a
484
502
      Right _                               -> do
485
503
        checkEqualities $ applySubst (makeSubstitution s) eqs
486
504
        let n = maximum $ (-1) : flex'
487
 
        return $ Unifies $ flattenSubstitution [ Map.lookup i s | i <- [0..n] ]
 
505
        return $ Unifies $ flattenSubstitution [ IntMap.lookup i s | i <- [0..n] ]
488
506
  `catchError` \err -> case err of
489
507
     TypeError _ (Closure {clValue = WithoutKError{}}) -> throwError err
490
508
     _                                                 -> return $ DontKnow err
513
531
    unifyConstructorArgs a12 vs1 vs2 = do
514
532
      liftTCM $ reportSDoc "tc.lhs.unify" 15 $ sep
515
533
        [ text "unifyConstructorArgs"
516
 
        -- , nest 2 $ parens (prettyTCM tel0)
517
 
        , nest 2 $ prettyList $ map prettyTCM vs1
518
 
        , nest 2 $ prettyList $ map prettyTCM vs2
 
534
        -- , nest 2 $ parens (prettyTCM tel0)
 
535
        , nest 2 $ prettyList $ map prettyTCM vs1
 
536
        , nest 2 $ prettyList $ map prettyTCM vs2
519
537
        , nest 2 $ text "constructor type:" <+> prettyTCM a12
520
538
        ]
521
539
      let n = genericLength vs1
540
558
    unifyConArgs tel0@(ExtendTel a@(Dom _ bHH) tel) us0@(arg@(Arg _ u) : us) vs0@(Arg _ v : vs) = do
541
559
      liftTCM $ reportSDoc "tc.lhs.unify" 15 $ sep
542
560
        [ text "unifyConArgs"
543
 
        -- , nest 2 $ parens (prettyTCM tel0)
544
 
        , nest 2 $ prettyList $ map prettyTCM us0
545
 
        , nest 2 $ prettyList $ map prettyTCM vs0
546
 
        , nest 2 $ text "at telescope" <+> prettyTCM bHH <+> text "..."
 
561
        -- , nest 2 $ parens (prettyTCM tel0)
 
562
        , nest 2 $ prettyList $ map prettyTCM us0
 
563
        , nest 2 $ prettyList $ map prettyTCM vs0
 
564
        , nest 2 $ text "at telescope" <+> prettyTCM bHH <+> text "..."
547
565
        ]
548
566
      liftTCM $ reportSDoc "tc.lhs.unify" 25 $
549
567
        (text $ "tel0 = " ++ show tel0)
582
600
    unifyElims a us0@(Apply arg@(Arg _ u) : us) vs0@(Apply (Arg _ v) : vs) = do
583
601
      liftTCM $ reportSDoc "tc.lhs.unify" 15 $ sep
584
602
        [ text "unifyElims"
585
 
        , nest 2 $ parens (prettyTCM a)
586
 
        , nest 2 $ prettyList $ map prettyTCM us0
587
 
        , nest 2 $ prettyList $ map prettyTCM vs0
 
603
        , nest 2 $ parens (prettyTCM a)
 
604
        , nest 2 $ prettyList $ map prettyTCM us0
 
605
        , nest 2 $ prettyList $ map prettyTCM vs0
588
606
        ]
589
607
      a <- ureduce a  -- Q: reduce sufficient?
590
608
      case ignoreSharing $ unEl a of
591
 
        Pi b _  -> do
 
609
        Pi b _  -> do
592
610
          -- Andreas, Ulf, 2011-09-08 (AIM XVI)
593
611
          -- in case of dependent function type, we cannot postpone
594
612
          -- unification of u and v, otherwise us or vs might be ill-typed
595
613
          let dep = dependent $ unEl a
596
614
          -- skip irrelevant parts
597
 
          unless (isIrrelevant b) $
 
615
          unless (isIrrelevant b) $
598
616
            (if dep then noPostponing else id) $
599
617
              unify (unDom b) u v
600
618
          arg <- traverse ureduce arg
601
 
          unifyElims (a `piApply` [arg]) us vs
602
 
        _         -> __IMPOSSIBLE__
 
619
          unifyElims (a `piApply` [arg]) us vs
 
620
        _         -> __IMPOSSIBLE__
603
621
      where dependent (Pi _ NoAbs{}) = False
604
622
            dependent (Pi b c)       = 0 `relevantIn` absBody c
605
623
            dependent (Shared p)     = dependent (derefPtr p)
613
631
    unifyArgs a us0@(arg@(Arg _ u) : us) vs0@(Arg _ v : vs) = do
614
632
      liftTCM $ reportSDoc "tc.lhs.unify" 15 $ sep
615
633
        [ text "unifyArgs"
616
 
        , nest 2 $ parens (prettyTCM a)
617
 
        , nest 2 $ prettyList $ map prettyTCM us0
618
 
        , nest 2 $ prettyList $ map prettyTCM vs0
 
634
        , nest 2 $ parens (prettyTCM a)
 
635
        , nest 2 $ prettyList $ map prettyTCM us0
 
636
        , nest 2 $ prettyList $ map prettyTCM vs0
619
637
        ]
620
638
      a <- ureduce a  -- Q: reduce sufficient?
621
639
      case ignoreSharing $ unEl a of
622
 
        Pi b _  -> do
 
640
        Pi b _  -> do
623
641
          -- Andreas, Ulf, 2011-09-08 (AIM XVI)
624
642
          -- in case of dependent function type, we cannot postpone
625
643
          -- unification of u and v, otherwise us or vs might be ill-typed
626
644
          let dep = dependent $ unEl a
627
645
          -- skip irrelevant parts
628
 
          unless (isIrrelevant b) $
 
646
          unless (isIrrelevant b) $
629
647
            (if dep then noPostponing else id) $
630
648
              unify (unDom b) u v
631
649
          arg <- traverse ureduce arg
632
 
          unifyArgs (a `piApply` [arg]) us vs
633
 
        _         -> __IMPOSSIBLE__
 
650
          unifyArgs (a `piApply` [arg]) us vs
 
651
        _         -> __IMPOSSIBLE__
634
652
      where dependent (Pi _ NoAbs{}) = False
635
653
            dependent (Pi b c)       = 0 `relevantIn` absBody c
636
654
            dependent (Shared p)     = dependent (derefPtr p)
678
696
     -> Term -> Term -> Unify ()
679
697
    unifyHH aHH u v = do
680
698
      liftTCM $ reportSDoc "tc.lhs.unify" 15 $
681
 
        sep [ text "unifyHH"
682
 
            , nest 2 $ (parens $ prettyTCM u) <+> text "=?="
683
 
            , nest 2 $ parens $ prettyTCM v
684
 
            , nest 2 $ text ":" <+> prettyTCM aHH
685
 
            ]
 
699
        sep [ text "unifyHH"
 
700
            , nest 2 $ (parens $ prettyTCM u) <+> text "=?="
 
701
            , nest 2 $ parens $ prettyTCM v
 
702
            , nest 2 $ text ":" <+> prettyTCM aHH
 
703
            ]
686
704
      u <- liftTCM . constructorForm =<< ureduce u
687
705
      v <- liftTCM . constructorForm =<< ureduce v
688
706
      aHH <- ureduce aHH
689
707
      liftTCM $ reportSDoc "tc.lhs.unify" 25 $
690
 
        sep [ text "unifyHH (reduced)"
691
 
            , nest 2 $ (parens $ prettyTCM u) <+> text "=?="
692
 
            , nest 2 $ parens $ prettyTCM v
693
 
            , nest 2 $ text ":" <+> prettyTCM aHH
694
 
            ]
 
708
        sep [ text "unifyHH (reduced)"
 
709
            , nest 2 $ (parens $ prettyTCM u) <+> text "=?="
 
710
            , nest 2 $ parens $ prettyTCM v
 
711
            , nest 2 $ text ":" <+> prettyTCM aHH
 
712
            ]
695
713
      -- obtain the (== Size) function
696
714
      isSizeName <- liftTCM isSizeNameTest
697
715
 
736
754
          (|->?) = maybeAssign fallback
737
755
 
738
756
      liftTCM $ reportSDoc "tc.lhs.unify" 15 $
739
 
        sep [ text "unifyAtom"
740
 
            , nest 2 $ prettyTCM u <> if flexibleTerm u then text " (flexible)" else empty
 
757
        sep [ text "unifyAtom"
 
758
            , nest 2 $ prettyTCM u <> if flexibleTerm u then text " (flexible)" else P.empty
741
759
            , nest 2 $ text "=?="
742
 
            , nest 2 $ prettyTCM v <> if flexibleTerm v then text " (flexible)" else empty
743
 
            , nest 2 $ text ":" <+> prettyTCM aHH
744
 
            ]
 
760
            , nest 2 $ prettyTCM v <> if flexibleTerm v then text " (flexible)" else P.empty
 
761
            , nest 2 $ text ":" <+> prettyTCM aHH
 
762
            ]
745
763
      liftTCM $ reportSDoc "tc.lhs.unify" 60 $
746
764
        text $ "aHH = " ++ show aHH
747
765
      case (ignoreSharing u, ignoreSharing v) of
753
771
        (_, Level l) -> do
754
772
            v <- liftTCM $ reallyUnLevelView l
755
773
            unifyAtomHH aHH u v tryAgain
756
 
        (Var i us, Var j vs) | i == j  -> checkEqualityHH aHH u v
 
774
        (Var i us, Var j vs) | i == j  -> checkEqualityHH aHH u v
757
775
-- Andreas, 2013-03-05: the following flex/flex case is an attempt at
758
776
-- better dotting (see Issue811).  Does not work perfectly, maybe the best choice
759
777
-- which variable to assign cannot made locally, but would need a look at the full
769
787
            -- (in this order, see Problem.hs).
770
788
            -- The comparison is total.
771
789
            if fj >= fi then j |->? (u, a) else i |->? (v, a)
772
 
        (Var i [], _) | homogeneous && flexible i -> i |->? (v, a)
773
 
        (_, Var j []) | homogeneous && flexible j -> j |->? (u, a)
774
 
        (Con c us, Con c' vs)
 
790
        (Var i [], _) | homogeneous && flexible i -> i |->? (v, a)
 
791
        (_, Var j []) | homogeneous && flexible j -> j |->? (u, a)
 
792
        (Con c us, Con c' vs)
775
793
          | c == c' -> do
776
794
              r <- liftTCM (dataOrRecordTypeHH' c aHH)
777
795
              case r of
791
809
                Nothing -> checkEqualityHH aHH u v
792
810
          | otherwise -> constructorMismatchHH aHH u v
793
811
        -- Definitions are ok as long as they can't reduce (i.e. datatypes/axioms)
794
 
        (Def d us, Def d' vs)
 
812
        (Def d us, Def d' vs)
795
813
          | d == d' -> do
796
814
              -- d must be a data, record or axiom
797
815
              def <- getConstInfo d
832
850
            if ok then unify a u v
833
851
                  else addEquality a u v
834
852
 
835
 
        (Con c us, _) -> do
 
853
        (Con c us, _) -> do
836
854
           md <- isEtaRecordTypeHH aHH
837
855
           case md of
838
856
             Just (d, parsHH) -> do
842
860
               unifyConstructorArgs bHH us vs
843
861
             Nothing -> fallback
844
862
 
845
 
        (_, Con c vs) -> do
 
863
        (_, Con c vs) -> do
846
864
           md <- isEtaRecordTypeHH aHH
847
865
           case md of
848
866
             Just (d, parsHH) -> do
854
872
 
855
873
        -- Andreas, 2011-05-30: If I put checkEquality below, then Issue81 fails
856
874
        -- because there are definitions blocked by flexibles that need postponement
857
 
        _  -> fallback
 
875
        _  -> fallback
858
876
 
859
877
 
860
878
    unify :: Type -> Term -> Term -> Unify ()