8

我试图理解为什么即使没有Pragma ,Haskellshow也会将字符列表与例如整数列表不同。FlexibleInstances

阅读了 的文档后Show,我意识到我并不真正理解 Haskell 如何为类型类的实例选择方法。

考虑以下代码:

class MyShow a where
    myShow :: a -> String
    myShowList :: [a] -> String
    myShowTuple :: (a, b) -> String

    myShowList xs = "Default List Implementation"
    myShowTuple t = "Default Tuple Implementation"

instance MyShow Char where
    myShow c = "One Char"
    myShowList xs = "List of Chars"
    myShowTuple t = "Char Tuple"

instance MyShow Int where
    myShow n = "One Int"
    myShowList xs = "List of Integers"
    myShowTuple t = "Int Tuple"

instance MyShow Float where
    myShow n = show n

instance (MyShow a) => MyShow [a] where
    myShow = myShowList

instance (MyShow a) => MyShow (a, b) where
    myShowTuple t = "foo"
    myShow = myShowTuple

现在如果我打电话给例如

myShow (5::Int,5::Int)

我希望 Haskell 认为‘哦,myShow有一个元组作为参数。让我们看看我必须调用哪个实现。并选择最后一个作为回报的结果"foo"。显然,事实并非如此。Haskell 似乎在看元组的内容(即 的类型a)并决定调用相应的方法,结果是"Int Tuple".

为什么是这样?

4

2 回答 2

9

当您编写 时myShow (5::Int, 5::Int),Haskell确实会说“哦,myShow 有一个元组作为参数。让我们看看我必须调用哪个实现。” 它确实选择了最后一个,即myShow = myShowTuple。但这并不意味着结果将是“foo”。这意味着调用的结果myShow (5::Int, 5::Int)将与调用的结果相同myShowTuple (5 :: Int, 5 :: Int)

所以现在 Haskell 必须决定myShowTuple它必须调用哪个版本。由于myShowTuple有 type ,倒数第二行定义MyShow a => (a, b) -> String的版本有 type ,所以不适合。第 17 行定义的那个有 type ,所以一个确实合适。所以这就是被选中的那个。myShowTupleMyShow a => ((a, c), b) -> String(Int, b) -> String

于 2013-06-02T17:44:52.930 回答
4

Haskell 的思维过程是这样的:

  1. 它试图找出MyShowfor(5 :: Int, 5 :: Int)(Int, Int)
  2. 然后它找到实例MyShow a => MyShow (a, b)
  3. 由于这统一,(a=>ab=> a)它选择这个实例。
  4. 它检查以确保a在这种情况下Int,它也是 的一个实例MyShow,它就是。注意:此检查在选择实例后进行。
  5. myShow (5 :: Int, 5 :: Int)调用元组myShow并变为myShowTuple (5 :: Int, 5 :: Int)
    • 它没有调用myShowTuple,因为它具有类型(a, b),并且在元组的情况下,具有a明显不匹配的类型。(a, b)myShowTuple((a, b) ,c)
  6. 这具有类型MyShow a => (a, b) -> String),并且由于a在这种情况下具有类型,因此Inthaskell 将其解析为的Int实例MyShow
  7. 它运行适当的myShowTuple
  8. 你得到"Int Tuple"

只是一个旁注,如果这是Show你想要这样的实际实现myShowTuple

myShowTuple :: MyShow b => (a, b) -> String

否则,您将无法实际格式化b任何类型的内容。

这将使

instance (MyShow a) => MyShow (a, b) where
  ...

进入

instance (MyShow a, MyShow b) => MyShow (a, b) where
  ... 
于 2013-06-02T17:45:33.080 回答