如果缺少约束,GHC 使用包罗万象的实例?
GHC uses catch-all instance if constraint is missing?
我一直在试验 HLists 的这个简单实现和函数 hasInt
如果 Int
是列表的成员,则 returns True
:
{-# 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
另一方面,如果我使用类型 class 函数但不包含约束,我通常希望 GHC 会抱怨,在这种情况下我没有得到任何此类指示。
显然它必须对 catch-all 实例做一些事情 IsInt a
。我会得到 Could not deduce (IsInt a) arising from a use of 'isInt'
如果我将 catch-all 实例替换为以下错误:
instance IsInt Bool where isInt _ = False
instance IsInt HNil where isInt _ = False
我的问题是:这是 GHC 的预期行为 - 如果没有显式类型 class 约束,它会默默地使用一个包罗万象的实例吗?
是的,这是预期的行为。如果你写
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 也知道存在这样的实例。
我一直在试验 HLists 的这个简单实现和函数 hasInt
如果 Int
是列表的成员,则 returns True
:
{-# 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
另一方面,如果我使用类型 class 函数但不包含约束,我通常希望 GHC 会抱怨,在这种情况下我没有得到任何此类指示。
显然它必须对 catch-all 实例做一些事情 IsInt a
。我会得到 Could not deduce (IsInt a) arising from a use of 'isInt'
如果我将 catch-all 实例替换为以下错误:
instance IsInt Bool where isInt _ = False
instance IsInt HNil where isInt _ = False
我的问题是:这是 GHC 的预期行为 - 如果没有显式类型 class 约束,它会默默地使用一个包罗万象的实例吗?
是的,这是预期的行为。如果你写
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 也知道存在这样的实例。