我正在研究GHC中函数重载的强大程度。我编写了以下代码:
class F_third_arg a where
run_f :: (Integer, a) -> Integer
instance F_third_arg Integer where
run_f (_, x) = x
instance F_third_arg String where
run_f (x, _) = x
my_fun :: (F_third_arg a) => Integer -> (a -> Integer)
my_fun x = \a -> run_f(x, a)
main :: IO ()
main = putStrLn $ show( ((my_fun::Integer->(Integer->Integer)) 5) $ 6)
(是的,我需要-XTypeSynonymInstances -XFlexibleInstances),我很惊讶编译器在调用时需要类型注释my_fun
。它应用于两个数字-推断此注释有什么问题?开启这两个扩展的重载规则是什么?
您的代码的问题在于数字文字本身已经过载。所以文字6
有类型Num a => a
,而my_fun 5
有类型F_third_arg b => b -> Integer
。因此,在类型推断期间,它将两个类型变量统一起来。但是由于没有其他要求,GHC在此处找不到要使用的具体类型,并给出了适当的错误消息:
test.hs:16:26: 没有因使用“ my_fun”而引起的(F_third_arg a0)实例 类型变量“ a0”含糊不清 可能的解决方法:添加一个可修复这些类型变量的类型签名 注意:几个可能的实例: instance F_third_arg字符串-在test.hs:9:10 定义。instance F_third_arg整数-在test.hs:6:10定义。 在表达式中:(my_fun 5) 在“ show”的第一个参数中,即`(((my_fun 5)$ 6)' 在第二个参数($)中,即show((my_fun 5)$ 6) test.hs:16:38: (Num a0)没有实例字面量“ 6”的 类型变量“ a0”不明确 可能解决方法:添加类型签名以修复这些类型变量 注意:有几种可能的实例: 实例Num Double-在'GHC.Float'中定义 实例Num Float-在'GHC.Float'实例中定义 整数a => Num(GHC.Real.Ratio a) -定义在``GHC.Real'' ... 在``($)''的第二个参数中加上其他三个,即``6'' 在``show''的第一个参数中即``((my_fun 5)$ 6)'' 在第二个参数中($)的值,即`show((my_fun 5)$ 6)'
有人可能希望编译器会注意到这Integer
是同时满足这两个要求的唯一类型,但是这种启发式方法会使您的代码相对脆弱,即,由于添加了新实例(例如F_third_arg Double
),它会中断。因此,编译器拒绝该代码,并要求您明确说明所涉及的类型。
您找到了一种解决它的方法,但是@leftroundabouts的使用建议6::Integer
更好一些。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句