сначала вещи, которые вы описываете, и подпись Either Int String
кажутся несоответствующими - я попробую сначала то, что вы описываете (выберите тип вывода по типу ввода):
вы можете сделать что-то очень похожее на то, что, я думаю, вы пытаетесь сделать с семействами типов:
{-# LANGUAGE TypeFamilies #-}
module SO where
data Foo = One | Two | Three deriving (Show, Read)
data Bar = This | That | TheOther deriving (Show, Read)
class PolyMap k where
type To k :: *
polyMap :: k -> To k
instance PolyMap Foo where
type To Foo = Int
polyMap _ = 123
instance PolyMap Bar where
type To Bar = String
polyMap _ = "string"
пример:
λ> polyMap One
123
λ> polyMap That
"string"
какое-то объяснение
Я думаю, что вы хотите иметь сопоставления типов/функции (нет проверки во время выполнения с typeOf
из коробки, и вместо этого вы получите хорошую поддержку проверки типов), и есть в основном два способа сделать это ( я в курсе)
Оба дают вам (среди прочего) средства, чтобы каким-то образом сказать: посмотрите, если я получу тип A, я могу сказать, каким должен быть некоторый связанный тип B (Foo -> Int
и Bar -> String
)
Это глубокая тема (пограничные зависимые типы;)), но я думаю, что семейства типов с классами несложно понять.
Идея, которую я использовал, состоит в том, чтобы иметь класс PolyMap
, который предоставляет функцию polyMap
(вы можете назвать его как угодно — doSomething
, как угодно), и там тип вывода зависит от типа ввода с использованием отображения To k
, которое Int
для Foo
и String
для Bar
, как указано в объявлениях экземпляров.
другой для вашей подписи еще проще:
doSomething :: Either Foo Bar -> Either Int String
doSomething (Left _) = Left 123
doSomething (Right _) = Right "string"
пример:
λ> doSomething (Left One)
Left 123
λ> doSomething (Right That)
Right "string"
person
Random Dev
schedule
25.11.2015