由于hmatrix为Matrix类型提供了Num的实例,我可以表达基于元素的减法:
m = (2><2)[1..] :: Double Matrix
m' = m - 3
效果很好,因为3
是Num
,并且会导致通过从m
的每个元素中减去3来创建矩阵。
为什么这不起作用:
m' = m - (3::Double)
我得到的错误是:
Couldn't match expected type ‘Matrix Double’
with actual type ‘Double’
In the second argument of ‘(-)’, namely ‘(3 :: Double)’
In the expression: m - (3 :: Double)
我希望编译器能够理解Double
也是Num
。为什么看起来不是这样?
答案 0 :(得分:7)
使用m - 3
m :: Matrix Double
3 :: Matrix Double
时,Matrix Double
会发生什么。 Num
是3
的实例的事实意味着编译器知道如何翻译文本m - (3 :: Double)
。但是,当您执行(-) :: (Num a) => a -> a -> a
时,由于Num
而出现类型错误,因此您减去的元素的类型必须是Double
的实例并且匹配。因此,您可以减去两个Matrix Double
,两个Matrix Double
,但不能减去Double
和 imageBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
。
毕竟,这对我来说似乎是合乎逻辑的,减去矩阵和标量是没有意义的。
答案 1 :(得分:5)
这是对Haskell基于类型的重载类型的新手的常见误解,特别是那些习惯于在流行的OO语言中使用的基于子类的重载的人。
减法运算符的类型为Num a => a -> a -> a
;所以它需要类型类Num
中的任何类型的两个参数。 似乎就像你做m - 3
时发生的那样是减法运算符在左边接受Matrix Double
而在右边接受一些简单的数字类型。但这实际上是不正确的。
当像Num a => a -> a -> a
这样的类型签名多次使用相同的类型变量时,您可以选择您喜欢的任何类型(在这种情况下,受=>
:Num a
之前的约束条件限制)要用于a
,但必须<{>>完全相同的类型 a
出现的地方。 Matrix Double -> Double -> ???
不是Num a => a -> a -> a
类型的有效实例化(如果是,您如何知道它返回的内容?)。
m - 3
工作的原因是因为两个参数必须是同一类型,而m
肯定是类型Matrix Double
,编译器会看到3
也必须是Matrix Double
类型。因此,它不使用源文本中出现的3
来构建Double
(或Integer
,或许多其他数字类型之一),而是使用源文本3
建立一个Matrix Double
。实际上,类型推断改变了编译器读取源代码文本3
的方式。
但是如果你使用m' = m - (3::Double)
那么你不会让它只是弄清楚3
必须具有什么类型才能使减法运算符有效,你告诉它3
1}}具体是Double
。 两个事实都没有办法(你的:: Double
断言以及减法运算符得到两个相同类型的参数的要求),所以你得到一个类型错误。