В Haskell перегрузка выполняется с использованием классов типов .Это сильно отличается от перегрузки в C #, поскольку классы типов больше похожи на интерфейсы в C #, хотя они также более мощные *.
Например, иметь функцию, которая сможет принимать либо Integer
или Bool
, вы можете написать что-то вроде этого:
class Foo a where
foo :: a -> String
instance Foo Integer where
foo n = show (n+42)
instance Foo Bool where
foo b = if b then "Hello" else "Goodbye"
Проверяя это в интерпретаторе, мы видим, что функция foo
имеет тип с ограничениями.
*Main> :t foo
foo :: Foo a => a -> String
Это означает, что функция будет работать для типов a
, для которых мы определили экземпляр Foo
.
*Main> foo 1295
"1337"
*Main> foo False
"Goodbye"
Если мы попытаемся использовать его для типадля которого нет такого экземпляра, мы получаем ошибку.
*Main> foo "Hello"
<interactive>:1:1:
No instance for (Foo [Char])
arising from a use of `foo'
Possible fix: add an instance declaration for (Foo [Char])
In the expression: foo "Hello"
In an equation for `it': it = foo "Hello"
Для вашего примера, я не думаю, что очень полезно перегрузить эту функцию таким способом в Haskell.Фактически, функция lcm
в стандартной библиотеке уже перегружена.
*Main> :t lcm
lcm :: Integral a => a -> a -> a
Это означает, что она будет работать с любым типом, для которого существует экземпляр Integral
.В данном случае это все целочисленные типы, включая машинный размер Int
, произвольный размер Integer
и другие, такие как Int32
, Int64
и т. Д.
Версия списка может быть записана как foldl1' lcm
, поэтому в первую очередь такая перегрузка может не потребоваться.
* С одной стороны, экземпляры класса типов передаются отдельно отобъекты, к которым они относятся.Это делает такие вещи, как многократная отправка, намного чище.Это также означает, что вы можете перегрузить возвращаемый тип функции, что было бы невозможно в C #.Классы типов также могут использоваться с конструкторами типа ;Monad
, пожалуй, самый известный пример такого типа классов.