hoogle-3.1: src/Hoogle/MatchClass.hs
{-
This file is part of Hoogle, (c) Neil Mitchell 2004-2005
http://www.cs.york.ac.uk/~ndm/hoogle/
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike License.
To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/2.0/
or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
-}
module Hoogle.MatchClass(
ClassTable,
buildClass,
lookupClass
) where
import Hoogle.Result
import Hoogle.TypeSig
import Hoogle.General
import Data.Maybe
import qualified Data.Map as Map
data ClassTable = ClassTable (Map.Map String [TypeMatch])
deriving Show
data TypeMatch = TypeMatch [Type] Constraint
deriving Show
-- item should only be instances
buildClass :: [Item] -> ClassTable
buildClass xs = ClassTable $ foldr add Map.empty (map f xs)
where
f (Instance (con, TList (TLit name:typs))) = (name, TypeMatch (f typs) (f con))
where
free = zip (allTVar (TList typs)) [0..]
f = map (mapUnbound g)
g x = TNum $ fromJust $ lookup x free
add (name, value) mp = case Map.lookup name mp of
Just x -> Map.insert name (value:x) mp
Nothing -> Map.insert name [value] mp
-- return ClassMinor if something is minorly wrong, i.e. no Show for a
-- return ClassMajor for bigger errors, no FooBar for a
lookupClass :: ClassTable -> Constraint -> String -> [Type] -> Maybe [MatchAmount]
lookupClass ct given check xs | all isTVar xs =
if any (== TList (TLit check : xs)) given then Just []
else if check `elem` ["Eq","Show","Ord"] then Just [ClassMinor]
else Just [ClassMajor]
-- either reduce or perish!
lookupClass c@(ClassTable ct) given check typ =
case mapMaybe f res of
[] -> Just [ClassMajor]
(x:xs) -> Just x
where
ltyp = length typ
res = Map.findWithDefault [] check ct
f (TypeMatch typ2 con)
| length typ2 == ltyp && isJust unifs && isJust res
= Just $ fromJust res
where
unifs = concatIdMaybeAll $ zipWith g typ2 typ
cons2 = map (mapNumber (\x -> fromJust $ lookup x (fromJust unifs))) con
res = concatMapMaybeAll ren cons2
ren (TList (TLit x:xs)) = lookupClass c given x xs
f _ = Nothing
-- type on the left must have the numbers in
g :: Type -> Type -> Maybe [(Int, Type)]
g (TNum x) y = Just [(x, y)]
g (TLit x) (TLit y) | x == y = Just []
g (TList x) (TList y) | length x == length y = concatIdMaybeAll $ zipWith g x y
g _ _ = Nothing