GHC использует универсальный экземпляр, если ограничение отсутствует?
Я экспериментировал с этой простой реализацией HLists и функцией hasInt
который возвращается True
если Int
является членом списка:
{-# LANGUAGE FlexibleInstances #-}
data HNil = HNil
deriving (Show, Read)
data HCons a b = HCons a b
deriving (Show, Read)
class HasInt a where
hasInt :: a -> Bool
instance HasInt HNil where
hasInt _ = False
instance HasInt as => HasInt (HCons a as) where
hasInt (HCons a as) = (isInt a) || (hasInt as)
class IsInt a where
isInt :: a -> Bool
instance IsInt Int where
isInt _ = True
instance {-# OVERLAPPABLE #-} IsInt a where
isInt _ = False
three = 3 :: Int
main = do
putStrLn $ "isInt three = " ++ show (isInt three) -- True
putStrLn $ "isInt True = " ++ show (isInt True) -- False
print $ hasInt $ HCons three $ HCons True HNil -- False ???
Это не дает ожидаемых результатов. Тем не менее, это похоже на работу, если я изменяю:
instance HasInt as => HasInt (HCons a as) where
чтобы:
instance (IsInt a, HasInt as) => HasInt (HCons a as) where
С другой стороны, я обычно ожидаю, что GHC будет жаловаться, если я использую функцию класса type, но не включаю ограничение, и я не получаю никаких таких указаний в этом случае.
Понятно, что это должно что-то делать с экземпляром catch-all IsInt a
, Я получу Could not deduce (IsInt a) arising from a use of 'isInt'
ошибка, если я заменяю универсальный экземпляр на:
instance IsInt Bool where isInt _ = False
instance IsInt HNil where isInt _ = False
У меня такой вопрос: является ли это ожидаемым поведением GHC - что он будет беззвучно использовать универсальный экземпляр, если нет явного ограничения класса типа?
1 ответ
Да, это ожидаемое поведение. Если ты пишешь
instance Foo a
вы заявляете, что все типы являются Foo
и GHC вам верит.
Это на 100% аналогично следующему:
foo :: Int -> Bool
foo x = x > 0
Даже если у вас нет Ord Int
в контексте GHC знает, что есть такой случай. Аналогично, в:
bar :: a -> b
bar x = {- use the Foo instance for x here -}
Даже если у вас нет Foo a
в контексте GHC знает, что есть такой случай.