Это путает два разных типа полиморфизма. То, что вы хотите, это ad-hoc полиморфизм, который осуществляется через классы типов. Типом полиморфизма функции типа a -> Int
является параметрический полиморфизм. При параметрическом полиморфизме одно определение функции для choice
должно работать для любой возможный тип a
. В этом случае это означает, что он фактически не может использовать значение типа a
, так как он ничего не знает об этом, поэтому choice
должен быть постоянной функцией, такой как choice _ = 3
. Это на самом деле дает вам очень сильные гарантии того, что функция может делать, просто взглянув на его тип (это свойство называется параметрием).
С классом типа, вы можете реализовать свой пример, как:
class ChoiceClass a where
choice :: a -> Int
instance ChoiceClass Int where
choice _ = 0
instance ChoiceClass String where
choice _ = 1
instance ChoiceClass a where
choice _ = 2
Теперь, я должен отметить, что этот класс типа подход часто неправильно один особенно, когда кто-то, кто только начинает хочет использовать его , Вы определенно не хотите делать это, чтобы избежать простого типа типа Choice
в вашем вопросе. Он может добавить много сложности, и разрешение экземпляра может сбить с толку вначале. Обратите внимание, что для того, чтобы получить решение типа класса, необходимо было включить два расширения: FlexibleInstances
и TypeSynonymInstances
с String
- синоним [Char]
. OverlappingInstances
также необходим, поскольку классы классов работают над допуском «открытого мира» (что означает, что кто-то может позже прийти и добавить экземпляр для нового типа, и это необходимо учитывать). Это не обязательно Плохая вещь, но вот это признак ползучей сложности, вызванной использованием решения типа класса по гораздо более простому решению типа данных. OverlappingInstances
, в частности, может усложнить работу и работать.
'Data.Typeable' позволяет запрашивать типы во время выполнения, но это не следует использовать слегка. – chi