![](/img/trans.png)
[英]Why can't I remove the Ord Typeclass from this haskell implementation of Kadane's algorithm?
[英]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中的对象上调用它)。 如果5
是Integer
,它确实实现了Ord
,那为什么我在REPL本身中调用compare
? 这显然是一个与我的范式转换有关的问题,我仍然没有得到它。 希望有人可以解释。
compare
等方法与类型相关联,而不是特定值。 编译器需要能够推断出类型以便选择正确的类型类实例,但这不需要任何特殊帮助。
compare
的类型是
compare :: (Ord a) => a -> a -> Ordering
因此,它的任何参数(类型a
)都可用于查找Ord
实例。
正如您所正确假设的那样,在compare 5 7
示例中, 5
和7
的类型默认为Integer
。 因此a
在compare
类型被推断为被Integer
和Ord 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.