[英]How does Haskell choose methods for instances of type classes?
我试图理解为什么即使没有FlexibleInstances
Pragma,Haskell的show
也会处理不同于整数列表的字符列表。
通读了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"
。 显然,事实并非如此。 哈斯克尔似乎看元组(即该类型的内容a
),并决定调用相应的方法,造成"Int Tuple"
。
为什么是这样?
当你编写myShow (5::Int, 5::Int)
,Haskell 会说“哦,myShow有一个元组作为参数。让我们看看我必须调用哪个实现。” 它确实选择了最后一个,即myShow = myShowTuple
。 但这并不意味着结果将是“foo”。 这意味着调用myShow (5::Int, 5::Int)
的结果与调用myShowTuple (5 :: Int, 5 :: Int)
的结果相同。
所以现在Haskell必须决定它必须调用哪个版本的myShowTuple
。 由于myShowTuple
类型为MyShow a => (a, b) -> String
,因此在myShowTuple
第二行上定义的myShowTuple
版本的类型为MyShow a => ((a, c), b) -> String
,所以一个人不合适。 第17行定义的那个类型(Int, b) -> String
,因此一个适合。 这就是被选中的那个。
Haskell的思维过程是这样的:
(5 :: Int, 5 :: Int)
或(Int, Int)
的MyShow
实例 MyShow a => MyShow (a, b)
a
=> a
和b
=> a
)它选择了这个实例。 a
,在这种情况下Int
,也是一个实例MyShow
,它是。 注意:选中实例后会进行此检查。 myShow (5 :: Int, 5 :: Int)
调用元组的myShow
并成为myShowTuple (5 :: Int, 5 :: Int)
myShowTuple
因为它有类型(a, b)
而在元组的情况下, a
是(a, b)
所以myShowTuple
的类型((a, b) ,c)
显然不匹配。 MyShow a => (a, b) -> String)
并且由于a
在这种情况下具有的类型Int
的Haskell可解决此到Int
的实例MyShow
myShowTuple
"Int Tuple"
只是一个旁注,如果这是Show
的实际实现,你需要为myShowTuple
这样的myShowTuple
myShowTuple :: MyShow b => (a, b) -> String
否则你无法实际格式化b
,毕竟是任何类型。
这会
instance (MyShow a) => MyShow (a, b) where
...
成
instance (MyShow a, MyShow b) => MyShow (a, b) where
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.