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。。。只有一个例子?您确定需要类型类吗?您可以阅读如何用数据结构替换类型类。(您没有执行存在类型类反模式,但这里的解析可能会起作用。)我会有很多实例,但所有实例都会产生相同的类型。