鉴于支持代码:
{-# LANGUAGE ExtendedDefaultRules, DeriveDataTypeable #-}
{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}
import Data.Typeable
default(A)
data A = A deriving (Eq,Show,Typeable)
class Show a => Testable2 a where
instance (Show a, Eq a) => Testable2 a where
instance (Show a, Testable2 b) => Testable2 (a -> b) where
instance (Show a, Show b) => Show (a -> b) where show _ = "<func>"
test :: (Show p, Typeable p, Testable2 p) => p -> IO ()
test = print . typeOf
Run Code Online (Sandbox Code Playgroud)
在GHC 7.6中,我可以写:
main = test (\f -> (f $))
Run Code Online (Sandbox Code Playgroud)
那种类型检查和打印:
(A -> A) -> A -> A
Run Code Online (Sandbox Code Playgroud)
但是,在GHC 7.8中,我得到:
Main.hs:
No instance for (Eq (a0 -> b0)) arising from a use of `test'
Run Code Online (Sandbox Code Playgroud)
但是,如果我重构:
main = let ff = \f -> (f $) in test ff
Run Code Online (Sandbox Code Playgroud)
然后它在GHC 7.8和GHC 7.6中都能正常工作.为什么?
该支持代码背后的逻辑是一个实例Show (a -> b)与Show上下文以迫使型违约,则处理默认原子(与方法Eq),并用一个移动的东西回来的方式->对Testable2.该代码旨在允许可变的QuickCheck属性,并取自hlint.
似乎test (\ x -> x)甚至无法使用 GHC 7.6.3 进行编译。另一方面:
($$) = ($)
main = test (\ f -> (f $$))
Run Code Online (Sandbox Code Playgroud)
两者都可以编译。我怀疑与特殊内置处理相结合的非广义/单态类型变量不会发生默认情况($)。
复制用户 kosmikus 对这个问题的评论。