Frank-0.3: Unify.lhs
> {-# OPTIONS_GHC -F -pgmF she #-}
> {-# LANGUAGE TypeOperators, FunctionalDependencies,
> FlexibleContexts #-}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> module Unify where
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> import Debug.Trace
> import Control.Newtype
> import Control.Applicative
> import Control.Monad
> import Control.Arrow
> import Data.Monoid
> import Data.Void
> import Data.Function
> import Data.List
> import Gubbins
> import Types
> import Template
> import Check
> import ElabMonad
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% Unification Class %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> class Unify t where
> (=?=) :: t -> t -> ElabM ()
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% Unification Instances %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> instance Unify VT where
> -- s =?= t | trace (show s ++ " =?= " ++ show t) False = undefined
> Ze =?= Ze = return ()
> Un =?= Un = return ()
> U b =?= U c = b =?= c
> D b us =?= D c vs | b == c = us =?= vs
> X i =?= X j | i == j = return ()
> Q i =?= Q j = if i == j then return () else identify i j
> Q i =?= v = solve i [] v
> v =?= Q i = solve i [] v
> s =?= t = moanE $ UnifyVFail s t
> instance Unify CT where
> (u :-> b) =?= (v :-> c) = do u =?= v; b =?= c
> F rr u =?= F ss v = do
> sortBy (compare `on` sigU) rr =?= sortBy (compare `on` sigU) ss
> u =?= v
> s =?= t = moanE $ UnifyCFail s t
> instance Unify Sig where
> (x :$ us) =?= (y :$ vs) | x == y = us =?= vs
> s =?= t = moanE $ UnifySFail s t
> instance Unify t => Unify [t] where
> [] =?= [] = return ()
> (a : as) =?= (b : bs) = do a =?= b; as =?= bs
> _ =?= _ = moanE $ Cockup "arity mismatch"
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% Occur Check %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> qoccur :: TMang t => Int -> t -> Bool
> qoccur q = ala' Any (ala' Const tMang) $
> var (const False) (const False) (q ==)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% Identification and Solving %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|identify i j| assumes |i| is not |j|
> identify :: Int -> Int -> ElabM ()
> identify i j = do
> --(g, _) <- getCxE
> --False <- trace ("IDENTIFY " ++ show g ++ show (i, j)) $ return False
> withTopEntry $ \ e -> case e of
> k :=? Nothing
> | k == i -> return (B0 :< (k :=? Just (Q j)))
> | k == j -> return (B0 :< (k :=? Just (Q i)))
> k :=? Just v
> | k == i -> solve j [] v >> return (B0 :< e)
> | k == j -> solve i [] v >> return (B0 :< e)
> _ -> identify i j >> return (B0 :< e)
|solve q es v| assumes |v| is not |Q q|
> solve :: Int -> [Entry] -> VT -> ElabM ()
> solve q es v = do
> (g, _) <- getCxE
> -- False <- trace ("SOLVE " ++ show g ++ show (q, es, v)) $ return False
> withTopEntry $ \ e -> case e of
> q' :=? mu | q' == q ->
> if qoccur q es || qoccur q v
> then moanE $ UnifyVFail (Q q) v
> else case mu of
> Nothing -> return (B0 <>< es :< (q :=? Just v))
> Just u -> do modCxE ((<>< es) *** id); u =?= v; return (B0 :< e)
> q' :=? _ | qoccur q' es || qoccur q' v -> solve q (e : es) v >> return B0
> e -> solve q es v >> return (B0 :< e)