繁体   English   中英

为什么我可以直接在REPL中调用类型类实例中的函数(比如从Ord比较)?

[英]Why can I call a function from a typeclass instance directly in the REPL (like compare from Ord)?

当我在像回忆录的GHCI这样的REPL中,我写道

*> compare 5 7
LT

为什么我可以直接在REPL中调用该函数( compare )?

我知道compare是在类型类Ord定义的。 Ord的类型类定义当然表明它是Eq的子类。

这是我的推理线: 5类型为Num a => a ,而Num类型类不是Eq的子类。 也,

Prelude> :t (compare 5)
(compare 5) :: (Num a, Ord a) => a -> Ordering

因此,当我应用数字类型参数时,会有一个额外的约束。 当我调用compare 5 7 ,参数的类型被缩小到具有Ord实例的东西。 我认为缩小发生在与类型类关联的默认具体类型:在Num的情况下,这是Integer ,它有一个Real实例,它有一个Ord实例。

但是,来自非函数式编程背景,我会想象我必须在其中一个数字上调用compare (比如在OOP中的对象上调用它)。 如果5Integer ,它确实实现了Ord ,那为什么我在REPL本身中调用compare 这显然是一个与我的范式转换有关的问题,我仍然没有得到它。 希望有人可以解释。

这种类型的违约发挥作用。 解释器可以推导出57需要属于同一类型,以及OrdNum类型类的成员。 Num的默认值是Integer ,因为Integer也是Ord一个实例,所以我们可以使用Integer

因此,在这种情况下,解释器将57视为Integer ,因此它可以评估函数并获得LT

GHCi有一些额外的默认规则,在GHCi文档中有描述。

compare等方法与类型相关联,而不是特定值。 编译器需要能够推断出类型以便选择正确的类型类实例,但这不需要任何特殊帮助。

compare的类型是

compare :: (Ord a) => a -> a -> Ordering

因此,它的任何参数(类型a )都可用于查找Ord实例。

正如您所正确假设的那样,在compare 5 7示例中, 57的类型默认为Integer 因此acompare类型被推断为被IntegerOrd Integer实例被选中。

此选择不一定通过函数参数。 考虑例如

read :: (Read a) => String -> a

这是驱动实例选择的结果类型,但类型检查器就可以了:

> read "(2, 3)" :: (Int, Int)
(2,3)

(OO等价物是什么? "(2, 3)".read() ?)

实际上,方法甚至不必是函数:

maxBound :: (Bounded a) => a

这是一个多态值,而不是函数:

> maxBound :: Int
9223372036854775807

类实例唯一地连接到​​类型,因此只要类型检查器有足够的信息来确定该类型变量代表什么,一切都可以解决。 也就是说,在

someMethod :: (SomeClass foo) => ...

foo必须出现在类型签名中的某处...所以类型检查器可以从someMethod在任何给定点使用的方式解析SomeClass foo (至少在没有某些语言扩展的情况下)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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