Это распространенное недоразумение людей, новых для стиля Haskell, связанных с перегрузкой на основе типов, особенно тех, кто используется для перегрузки на основе подкласса, используемой в популярных языках OO.
Оператор вычитания имеет тип Num a => a -> a -> a
; поэтому он принимает два аргумента любого типа, который находится в классе классов Num
. Это кажется нравится то, что происходит, когда вы делаете m - 3
, так это то, что оператор вычитания принимает Matrix Double
слева и некоторый простой числовой тип справа. Но это на самом деле неверно.
Когда типа подпись, как Num a => a -> a -> a
использует тот же тип переменные несколько раз, вы можете выбрать любой тип вы любите (в зависимости от contstraints перед =>
: 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
является конкретно Double
. Нет никакого пути к тому, чтобы быть правдой (ваше утверждение :: Double
и требование, чтобы оператор вычитания получал два аргумента одного и того же типа), поэтому вы получаете ошибку типа.
Обратите внимание, что Double - это конкретный экземпляр Num. «Matrix Double» - это еще один конкретный экземпляр Num, но для вычитания оба аргумента должны быть одного типа. – ErikR
Обратите внимание, что '3' на самом деле имеет тип' Matrix Double' в вашем примере. Номера перегружены в Haskell. – Alec