重叠实例——不清楚Haskell选择了哪个实例

重叠实例——不清楚Haskell选择了哪个实例,haskell,typeclass,Haskell,Typeclass,我有以下使用重叠实例的Haskell代码;我尝试实现一个函数,该函数将函数的类型生成为字符串,或者——更一般地说——对不同的函数类型执行不同的操作: {-# OPTIONS_GHC -fglasgow-exts #-} {-# LANGUAGE OverlappingInstances, IncoherentInstances #-} module Test where data TypeString = MKTS String instance Show TypeString wher

我有以下使用重叠实例的Haskell代码;我尝试实现一个函数,该函数将函数的类型生成为字符串,或者——更一般地说——对不同的函数类型执行不同的操作:

{-# OPTIONS_GHC -fglasgow-exts #-}
{-# LANGUAGE OverlappingInstances, IncoherentInstances #-}

module Test
where

data TypeString = MKTS String 

instance Show TypeString where
  show (MKTS s) = s

class ShowType b c where
  theType :: (b -> c) -> TypeString

instance ShowType b b where
  theType _ = MKTS "b -> b" 

instance ShowType b c where
  theType _ = MKTS "b -> c" 

instance ShowType (b, b') c where
  theType _ = MKTS "(b, b') -> c"

class Problem a where
  showProblem :: a -> TypeString

instance Problem (b -> c) where
  showProblem f = theType f
Haskell显示了我键入时的预期行为

> theType (uncurry (+))
(b,b') -> c
但是:有人能解释一下吗

> showProblem (uncurry (+))
b -> c

。。。并解释,如何避免Haskell选择太一般的实例的情况…

所使用的
问题的实例是为
b->c
制作的。如果查看
showProblem
的签名,您将看到没有
ShowType
上下文。如果没有上下文,编译器只能静态地推断实例。因此,选择了
b->c
的实例,因为它是静态适合的实例

我不知道如何解决这个问题,我想手工提供上下文是可行的,但我真的不知道:

class Problem a where
  showProblem :: ShowType a => a -> TypeString

instance Problem (b -> c) where
  showProblem :: ShoType (b -> c) => (b -> c) -> TypeString
  showProblem = theType

对我来说,使用OverlappingInstances通常意味着我在代码中做出了错误的设计决策。

我阅读了Haskell wiki中关于OverlappingInstances的内容。它说它有时有用,但我可以想象一个例子。@fuzzxk:。。。您提到,使用重叠意味着错误的决策;但是,整个数据、可键入模块和整个废弃样板文件不是基于重叠的实例吗?