Haskell中的不完全隐式类型推理 我们考虑下面的例子: data A = A{x::Int} deriving(Show) instance Func_f (A -> String) where f _ = "ala" class Func_f a where f :: a main :: IO () main = do let a = A 5 x = f a print 5
使用Haskell中的不完全隐式类型推理 我们考虑下面的例子: data A = A{x::Int} deriving(Show) instance Func_f (A -> String) where f _ = "ala" class Func_f a where f :: a main :: IO () main = do let a = A 5 x = f a print 5,haskell,types,overloading,type-inference,typeclass,Haskell,Types,Overloading,Type Inference,Typeclass,使用ghc-XFlexibleInstances main.hs编译 (我尝试了-xextendedfaultrules,但没有任何进展) 为什么编译时会出现错误 main.hs:25:21: No instance for (Func_f (A -> t0)) arising from a use of `f' The type variable `t0' is ambiguous Possible fix: add a type signature that f
ghc-XFlexibleInstances main.hs编译
(我尝试了-xextendedfaultrules
,但没有任何进展)
为什么编译时会出现错误
main.hs:25:21:
No instance for (Func_f (A -> t0)) arising from a use of `f'
The type variable `t0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there is a potential instance available:
instance Func_f (A -> String) -- Defined at main.hs:7:10
Possible fix: add an instance declaration for (Func_f (A -> t0))
In the expression: f a
In an equation for `x': x = f a
In the expression:
do { let a = A 5
x = f a;
print 5 }
Func_f只有一个实例,因此Haskell应该能够知道x=f a
的结果。您可以通过手动提供类型来修复错误,例如:x=f a::String
,但这不适合我的情况,因为我正在生成Haskell代码,我希望Haskell的类型推断器能为我完成这项工作。您遇到了问题。基本思想是GHC总是假设您可以向代码中添加更多的类实例。此外,您无法控制如何在模块之间导出和导入实例。因此,仅仅依靠一个特定类的实例是行不通的,并且会导致奇怪的bug
从本质上讲,没有任何东西可以阻止您或其他人编写另一个实例,如:
instance Func_f (A -> Int) where
f _ = 10
这样就不可能在代码中找到你想要的。这可能会导致您的代码从链接到另一个模块时中断
但是,如果您实际使用了该值,它的类型很可能会受到其他参数的约束,模糊性就会消失。例如,以下工作:
main :: IO ()
main = do
let a = A 5
x = f a
putStr x
基本上,这是其中一种情况(类似于read.show
),其中类型签名是不可避免的,因为GHC是如何处理类型类实例的
Func_f只有一个实例,因此Haskell应该能够知道x=f a的结果
这违反了在这个特殊的例子中,我们能要求Haskell遵守这个规则吗?我知道这通常会很糟糕,但我正在生成Haskell代码,我知道这种情况不会发生。嗯,不是真的。您可以通过指定类型签名来完成此操作:P.Hmmm。。。只有一个例子?您确定需要类型类吗?您可以阅读如何用数据结构替换类型类。(您没有执行存在类型类反模式,但这里的解析可能会起作用。)我会有很多实例,但所有实例都会产生相同的类型。