繁体   English   中英

Haskell如何为类型类的实例选择方法?

[英]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的思维过程是这样的:

  1. 它试图找出(5 :: Int, 5 :: Int)(Int, Int)MyShow实例
  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在这种情况下具有的类型Int的Haskell可解决此到Int的实例MyShow
  7. 它运行适当的myShowTuple
  8. 你得到"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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM