должен полностью описать, что вы можете с ним сделать. Если вы можете вызывать его только для определенных типов, это должно отражать сигнатура типа.
тоящее время я пытаюсь обернуть голову вокруг типов классов и экземпляров, и пока не совсем понимаю их смысл. У меня есть два вопроса по этому вопросу:
1) Почему необходимо иметь класс типа в сигнатуре функции, когда функция использует некоторую функцию из этого класса типов. Пример:
f :: (Eq a) => a -> a -> Bool
f a b = a == b
Зачем ставить(Eq a)
в подписи. Если==
не определено дляa
тогда почему бы просто не скинуть ошибку при встречеa == b
? Какой смысл в том, чтобы объявлять класс типа впереди?
2) Как связаны классы типов и перегрузка функций?
Это невозможно сделать:
data A = A
data B = B
f :: A -> A
f a = a
f :: B -> B
f b = b
Но это можно сделать так:
data A = A
data B = B
class F a where
f :: a -> a
instance F A where
f a = a
instance F B where
f b = b
Что с этим? Почему у меня не может быть двух функций с одинаковым именем, но работающих на разных типах ... Исходя из C ++, я нахожу это очень странным. Но у меня, вероятно, неправильные представления о том, что это на самом деле. но как только я заверну их в эти экземпляры класса типов, я смогу.
Не стесняйтесь подбрасывать мне категории или вводить теоретические слова, так как я изучаю эти предметы параллельно с изучением Haskell, и я подозреваю, что в них есть теоретическая основа для того, как Haskell делает вещи здесь.