module Test where
data Type = TInteger | TBoolean
data CmpPredicate = GreatherThan
data BinaryOperation = Plus
data Expression = ArithOp BinaryOperation Expression Expression
| BoolOp CmpPredicate Expression Expression
| ConstI Integer
class Operation op where
resultType :: op -> Type -> Type -> Type
instance Operation CmpPredicate where
resultType op a b = TBoolean
instance Operation BinaryOperation where
resultType op a b = TInteger
-- Если объявить тип, то всё нормально.
-- deduceOperationTypes :: Operation op => op -> Expression -> Expression -> Type
deduceOperationTypes op e1 e2 =
let
t1 = deduceTypes e1
t2 = deduceTypes e2
in (resultType op t1 t2)
deduceTypes (ConstI _) = TInteger
--
-- Если закомментировать оба следущих утверждения, то тип deduceOperationTypes
-- выводится правильно.
deduceTypes (BoolOp op e1 e2) = deduceOperationTypes op e1 e2
-- Если закомментировать только эту строчку, то тип
-- deduceOperationTypes выводится как
-- deduceOperationTypes :: CmpPredicate -> Expression -> Expression -> Type
deduceTypes (ArithOp op e1 e2) = deduceOperationTypes op e1 e2
-- Если не комментировать ни одной, то получаем сообщение о конфликте типов
-- в предыдущей строке
-- dev-lang/ghc 7.6.3-r1 (Gentoo), тип проверялся с помощью
-- :t deduceOperationTypes в ghci